@task-handoff/node-agent 0.0.9-alpha.3 → 0.0.9-alpha.5
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/package.json +1 -1
- package/runtime-artifacts/{controlled-instance-runtime-0.0.9-alpha.3-linux-universal.manifest.json → controlled-instance-runtime-0.0.9-alpha.5-linux-universal.manifest.json} +2 -2
- package/runtime-artifacts/controlled-instance-runtime-0.0.9-alpha.5-linux-universal.tar.gz +0 -0
- package/runtime-artifacts/controlled-instance-runtime-0.0.9-alpha.5-linux-universal.tar.gz.sha256 +1 -0
- package/runtime-artifacts/controlled-instance-runtime-0.0.9-alpha.3-linux-universal.tar.gz +0 -0
- package/runtime-artifacts/controlled-instance-runtime-0.0.9-alpha.3-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"),r=require("node:http"),i=require("node:net"),s=require("node:url"),o=require("node:child_process"),a=require("node:stream"),c=require("fastify"),d=require("@fastify/websocket"),l=require("ws"),u=require("zod"),m=require("node:crypto"),p=require("node-pty"),h=require("node:os"),g=require("write-file-atomic"),f=require("semver"),I=require("node:fs/promises"),y=require("node:stream/promises"),A=require("tar"),b="undefined"!=typeof document?document.currentScript:null;const w=41943040,N="ai.sessions",z=u.z.string().trim().min(1).max(80),v=u.z.enum(["running","waiting","idle","failed"]);u.z.object({instanceId:u.z.string().trim().min(1).max(160),sessionId:u.z.string().trim().min(1).max(120),unread:u.z.boolean(),sessionUpdatedAt:u.z.string().datetime(),updatedAt:u.z.string().datetime()}).strict();const E=u.z.enum(["thinking","tool","editing","approval","responding","unknown"]),S=u.z.object({id:u.z.string().trim().min(1).max(240).optional(),kind:u.z.string().trim().min(1).max(80).optional(),name:u.z.string().trim().min(1).max(120),inputPreview:u.z.string().trim().max(500).optional(),startedAt:u.z.string().datetime().optional()}).strict(),_=u.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),T=u.z.enum(["started","interacted","interrupted"]),k=u.z.object({threadId:u.z.string().trim().min(1).max(240),path:u.z.string().trim().max(4096).optional(),status:_,activity:T.optional(),message:u.z.string().trim().max(1e3).optional(),updatedAt:u.z.string().datetime()}).strict(),C=u.z.object({toolCalls:u.z.number().int().min(0).default(0),edits:u.z.number().int().min(0).default(0),approvals:u.z.number().int().min(0).default(0)}).strict().default({toolCalls:0,edits:0,approvals:0}),x=u.z.object({send:u.z.boolean().optional(),interrupt:u.z.boolean().optional(),approval:u.z.boolean().optional()}).strict(),O=u.z.enum(["image","file"]),R=u.z.object({id:u.z.string().trim().min(1).max(120),kind:O,name:u.z.string().trim().min(1).max(240),mime:u.z.string().trim().min(1).max(120),size:u.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)}),D=u.z.union([R.extend({source:u.z.object({type:u.z.literal("inline"),encoding:u.z.literal("base64"),data:u.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:u.z.ZodIssueCode.custom,path:["size"],message:`Inline ${e.kind} must be between 1 byte and ${n} bytes.`})}),R.extend({source:u.z.object({type:u.z.literal("runtime-path"),path:u.z.string().trim().min(1).max(4096)}).strict()}).strict()]),j=R.extend({sourceType:u.z.enum(["inline","runtime-path"])}).strict(),P=u.z.union([u.z.object({id:u.z.string().trim().min(1).max(120),kind:O.optional(),source:u.z.object({type:u.z.literal("upload-ref")}).strict().default({type:"upload-ref"})}).strict(),u.z.object({id:u.z.string().trim().min(1).max(120),kind:O,name:u.z.string().trim().min(1).max(240),mime:u.z.string().trim().min(1).max(120),size:u.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),source:u.z.object({type:u.z.literal("runtime-path"),path:u.z.string().trim().min(1).max(4096)}).strict()}).strict()]),M=u.z.enum(["auto","queue","steer","immediate"]),L=u.z.enum(["ask","auto-review","full-access"]),$=u.z.enum(["review","rename","goal","compact"]);u.z.object({command:$,argument:u.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.`})}),u.z.object({command:$,value:u.z.string().max(4e3).optional(),turnId:u.z.string().trim().min(1).max(240).optional()}).strict(),u.z.enum(["skill","app","plugin"]);const F=u.z.object({name:u.z.string().trim().min(1).max(240),path:u.z.string().trim().min(1).max(4096)}),U=u.z.discriminatedUnion("kind",[F.extend({kind:u.z.literal("skill"),path:u.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/"),"Skill paths must be absolute.")}).strict(),F.extend({kind:u.z.literal("app"),path:u.z.string().trim().min(7).max(4096).regex(/^app:\/\/[^\s/]+$/,"App paths must use app://<id>.")}).strict(),F.extend({kind:u.z.literal("plugin"),path:u.z.string().trim().min(10).max(4096).regex(/^plugin:\/\/[^\s/]+$/,"Plugin paths must use plugin://<id>.")}).strict()]),V=u.z.array(U).max(20).default([]),H=u.z.enum(["plugin","skill","file","directory","app"]),q=u.z.object({kind:H,name:u.z.string().trim().min(1).max(240),description:u.z.string().trim().max(1e3).optional(),path:u.z.string().trim().min(1).max(4096),icon:u.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."})}),B=u.z.object({category:u.z.enum(["skills","plugins","apps","files"]),code:u.z.string().trim().min(1).max(160),message:u.z.string().trim().min(1).max(2e3)}).strict();u.z.object({sessionId:u.z.string().trim().min(1).max(120),providerSessionId:u.z.string().trim().min(1).max(240),cwd:u.z.string().trim().min(1).max(4096),candidates:u.z.array(q).max(1e3).default([]),diagnostics:u.z.array(B).max(20).default([])}).strict(),u.z.object({query:u.z.string().trim().max(240).default("")}).strict(),u.z.object({sessionId:u.z.string().trim().min(1).max(120),cwd:u.z.string().trim().min(1).max(4096),query:u.z.string().trim().max(240),requestId:u.z.string().trim().min(1).max(160),candidates:u.z.array(q.refine(e=>"file"===e.kind||"directory"===e.kind,"File search only returns files and directories.")).max(200).default([]),complete:u.z.boolean().default(!1)}).strict();const K=u.z.object({message:u.z.string().trim().min(1).max(2e4),mode:M.optional(),permissionMode:L.optional()});K.extend({attachments:u.z.array(D).max(6).default([]),references:V}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>w&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),K.extend({attachments:u.z.array(P).max(6).default([]),references:V}).strict(),u.z.object({decision:u.z.enum(["allow","deny","skip"])}).strict(),u.z.object({queueIds:u.z.array(u.z.string().trim().min(1).max(120)).max(100)}).strict(),u.z.object({code:u.z.string().trim().min(1).max(160),message:u.z.string(),instanceId:u.z.string().trim().min(1).max(160).optional(),nodeId:u.z.string().trim().min(1).max(160).optional(),route:u.z.string().trim().min(1).max(4096).optional()}).strict();const G=u.z.object({id:u.z.string().trim().min(1).max(120),message:u.z.string().trim().min(1).max(2e4),attachments:u.z.array(j).max(6).default([]),references:V,permissionMode:L.optional(),status:u.z.enum(["queued","sending","failed"]).default("queued"),createdAt:u.z.string().datetime(),updatedAt:u.z.string().datetime(),error:u.z.string().trim().max(4e3).optional()}).strict(),J=u.z.object({pendingCount:u.z.number().int().min(0).default(0),items:u.z.array(G).max(100).default([])}).strict().default({pendingCount:0,items:[]}),W=u.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),Y=u.z.object({id:u.z.string().trim().min(1).max(240),status:u.z.enum(["running","completed"]),startedAt:u.z.string().datetime().optional(),completedAt:u.z.string().datetime().optional()}).strict(),X=u.z.object({id:u.z.string().trim().min(1).max(240),providerTurnId:u.z.string().trim().max(240).optional(),source:W.optional(),userPrompt:u.z.string().trim().optional(),status:u.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:E.optional(),summary:u.z.string().trim().max(1e3).optional(),lastMessage:u.z.string().trim().optional(),lastMessageItemId:u.z.string().trim().max(240).optional(),contextCompactions:u.z.array(Y).max(20).optional(),revision:u.z.number().int().min(0).default(0),sourcePriority:u.z.number().int().min(0).max(100).optional(),snapshotVersion:u.z.number().int().min(0).optional(),observedAt:u.z.string().datetime().optional(),startedAt:u.z.string().datetime().optional(),updatedAt:u.z.string().datetime().optional(),completedAt:u.z.string().datetime().optional()}).strict(),Z=X.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),Q=u.z.object({id:u.z.string().trim().min(1).max(120),agent:z,appSessionId:u.z.string().trim().max(120).optional(),appId:u.z.string().trim().max(120).optional(),providerSessionId:u.z.string().trim().max(240).optional(),providerMeta:u.z.record(u.z.string(),u.z.unknown()).optional(),appBindingKeys:u.z.array(u.z.string().trim().min(1).max(240)).max(20).optional(),actions:x.optional(),activeTurnId:u.z.string().trim().max(240).optional(),title:u.z.string().trim().max(240).optional(),cwd:u.z.string().trim().max(4096).optional(),userPrompt:u.z.string().trim().optional(),turns:u.z.array(X).max(50).optional(),status:v.default("running"),phase:E.default("unknown"),summary:u.z.string().trim().max(1e3).optional(),lastMessage:u.z.string().trim().optional(),lastMessageItemId:u.z.string().trim().max(240).optional(),currentTool:S.optional(),toolCallsSinceLastMessage:u.z.number().int().min(0).default(0),subAgents:u.z.array(k).max(50).default([]),transcriptPath:u.z.string().trim().max(4096).optional(),transcriptSize:u.z.number().int().min(0).optional(),startedAt:u.z.string().datetime(),updatedAt:u.z.string().datetime(),completedAt:u.z.string().datetime().optional(),error:u.z.string().trim().max(4e3).optional(),counters:C,queue:J}).strict();u.z.object({session:Q,provider:u.z.string().trim().min(1).max(80),action:u.z.enum(["send","queue","steer","interrupt","approval"]),decision:u.z.enum(["allow","deny","skip"]).optional(),turnId:u.z.string().trim().min(1).max(240).optional(),providerTurnId:u.z.string().trim().min(1).max(240).optional(),queueId:u.z.string().trim().min(1).max(120).optional()}).strict();const ee=u.z.object({id:u.z.string().trim().min(1).max(120),agent:u.z.enum(["codex","claude"]),providerSessionId:u.z.string().trim().min(1).max(240),title:u.z.string().trim().max(240).optional(),userPrompt:u.z.string().trim().optional(),lastMessage:u.z.string().trim().optional(),cwd:u.z.string().trim().min(1).max(4096),lastActiveAt:u.z.string().datetime(),archivedAt:u.z.string().datetime()}).strict();u.z.object({schemaVersion:u.z.literal(1).default(1),items:u.z.array(ee).max(50).default([])}).strict(),u.z.object({items:u.z.array(ee).max(50).default([])}).strict(),u.z.object({item:ee,turns:u.z.array(Z).max(50).default([])}).strict(),u.z.object({disposition:u.z.enum(["resumed","already-open"]),aiSessionId:u.z.string().trim().min(1).max(120),providerSessionId:u.z.string().trim().min(1).max(240),appSessionId:u.z.string().trim().min(1).max(120)}).strict();const te=Q.pick({id:!0,agent:!0,appSessionId:!0,appId:!0,providerSessionId:!0,providerMeta:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!0,userPrompt:!0,turns:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,lastMessageItemId:!0,currentTool:!0,toolCallsSinceLastMessage:!0,subAgents:!0,queue:!0,startedAt:!0,updatedAt:!0,error:!0}),ne=u.z.object({runningCount:u.z.number().int().min(0).default(0),waitingCount:u.z.number().int().min(0).default(0),staleCount:u.z.number().int().min(0).default(0),sessions:u.z.array(te).default([]),updatedAt:u.z.string().datetime()}).strict();u.z.object({streamId:u.z.string().trim().min(1).max(240),revision:u.z.number().int().min(0),lastEventAt:u.z.string().datetime(),snapshot:ne}).strict(),ne.pick({runningCount:!0,waitingCount:!0,staleCount:!0,updatedAt:!0}).extend({idleCount:u.z.number().int().min(0).default(0),problemCount:u.z.number().int().min(0).default(0),revision:u.z.number().int().min(0).optional()});const re=u.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),ie=u.z.object({streamId:u.z.string().trim().min(1).max(240),instanceId:u.z.string().trim().min(1).max(160),nodeId:u.z.string().trim().min(1).max(160).optional(),revision:u.z.number().int().min(0),previousRevision:u.z.number().int().min(0).optional(),traceId:u.z.string().trim().min(1).max(160),generatedAt:u.z.string().datetime(),reason:re}).strict(),se=u.z.object({meta:ie,snapshot:ne}).strict(),oe=u.z.object({meta:ie,upserted:u.z.array(te).default([]),removed:u.z.array(u.z.string().trim().min(1).max(120)).default([])}).strict(),ae=u.z.object({meta:ie,sessionIds:u.z.array(u.z.string().trim().min(1).max(120)).default([]),expiresAt:u.z.string().datetime()}).strict();u.z.object({instanceId:u.z.string().trim().min(1).max(160),nodeId:u.z.string().trim().min(1).max(160).optional(),sessionId:u.z.string().trim().min(1).max(120),providerSessionId:u.z.string().trim().min(1).max(240),turnId:u.z.string().trim().min(1).max(240),itemId:u.z.string().trim().min(1).max(240),delta:u.z.string().min(1),generatedAt:u.z.string().datetime()}).strict(),u.z.object({streamId:u.z.string().trim().min(1).max(240),instanceId:u.z.string().trim().min(1).max(160),sinceRevision:u.z.number().int().min(0),latestRevision:u.z.number().int().min(0),earliestRetainedRevision:u.z.number().int().min(0),syncRequired:u.z.boolean().default(!1),events:u.z.array(u.z.discriminatedUnion("type",[u.z.object({type:u.z.literal("ai-session.snapshot"),payload:se}).strict(),u.z.object({type:u.z.literal("ai-session.patch"),payload:oe}).strict(),u.z.object({type:u.z.literal("ai-session.removed"),payload:ae}).strict()])).default([])}).strict();const ce=u.z.object({source:W,sourcePriority:u.z.number().int().min(0).max(100).optional(),observedAt:u.z.string().datetime().optional(),snapshotVersion:u.z.number().int().min(0).optional()}).strict(),de=ce.extend({type:u.z.literal("snapshot"),agent:u.z.string().trim().min(1).max(80),appSessionId:u.z.string().trim().max(120).optional(),appId:u.z.string().trim().max(120).optional(),providerSessionId:u.z.string().trim().max(240).optional(),providerMeta:u.z.record(u.z.string(),u.z.unknown()).optional(),appBindingKeys:u.z.array(u.z.string().trim().min(1).max(240)).max(20).optional(),actions:x.optional(),title:u.z.string().trim().max(240).optional(),cwd:u.z.string().trim().max(4096).optional(),activeTurnId:u.z.string().trim().max(240).optional(),userPrompt:u.z.string().trim().optional(),turns:u.z.array(X).max(50).optional(),status:v.optional(),phase:E.optional(),summary:u.z.string().trim().max(1e3).optional(),lastMessage:u.z.string().trim().optional(),lastMessageItemId:u.z.string().trim().max(240).optional(),currentTool:S.optional(),toolCallsSinceLastMessage:u.z.number().int().min(0).optional(),subAgents:u.z.array(k).max(50).optional(),transcriptPath:u.z.string().trim().max(4096).optional(),transcriptSize:u.z.number().int().min(0).optional(),replaceActivity:u.z.boolean().optional()}).strict(),le=ce.extend({type:u.z.literal("event"),sessionId:u.z.string().trim().min(1).max(120),kind:u.z.enum(["lifecycle","send-ack","turn-started","user-message","assistant-message","approval-requested","turn-completed","tool-activity","sub-agent-activity","context-compaction"]),activeTurnId:u.z.string().trim().max(240).optional(),providerTurnId:u.z.string().trim().max(240).optional(),userPrompt:u.z.string().trim().optional(),text:u.z.string().optional(),itemId:u.z.string().trim().max(240).optional(),status:v.optional(),phase:E.optional(),summary:u.z.string().trim().max(1e3).optional(),error:u.z.string().trim().max(4e3).optional(),currentTool:S.nullable().optional(),toolCallsSinceLastMessage:u.z.number().int().min(0).optional(),subAgents:u.z.array(k).max(50).optional(),contextCompaction:Y.optional(),counters:u.z.object({toolCalls:u.z.number().int().min(0).optional(),edits:u.z.number().int().min(0).optional(),approvals:u.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"})});u.z.discriminatedUnion("type",[de,le]);const ue=u.z.union([u.z.object({type:u.z.literal("schedule"),scheduleKind:u.z.literal("interval").default("interval"),intervalMs:u.z.number().int().min(1e3)}).strict(),u.z.object({type:u.z.literal("schedule"),scheduleKind:u.z.literal("daily"),timeOfDay:u.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:u.z.string().trim().min(1).max(120)}).strict(),u.z.object({type:u.z.literal("schedule"),scheduleKind:u.z.literal("weekly"),weekdays:u.z.array(u.z.number().int().min(0).max(6)).min(1).max(7),timeOfDay:u.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:u.z.string().trim().min(1).max(120)}).strict()]),me=u.z.union([ue,u.z.object({type:u.z.literal("file-change"),roots:u.z.array(u.z.string().trim().min(1).max(4096)).min(1).max(50),globs:u.z.array(u.z.string().trim().min(1).max(500)).min(1).max(100),ignore:u.z.array(u.z.string().trim().min(1).max(500)).max(100).optional(),debounceMs:u.z.number().int().min(100).max(6e4).default(1500)}).strict(),u.z.object({type:u.z.literal("ai-session"),agent:u.z.string().trim().min(1).max(80).optional(),statuses:u.z.array(u.z.enum(["running","waiting","idle","failed"])).max(20).optional(),phases:u.z.array(u.z.enum(["thinking","tool","editing","approval","responding","unknown"])).max(20).optional()}).strict()]),pe=u.z.object({promptTemplate:u.z.string().trim().min(1).max(2e4)}).strict(),he=u.z.object({cooldownMs:u.z.number().int().min(0).max(864e5).optional(),maxConcurrentRuns:u.z.number().int().min(1).max(20).default(1),whenBusy:u.z.enum(["skip","queue"]).default("skip")}).strict(),ge=u.z.object({configHash:u.z.string().trim().min(8).max(80),name:u.z.string().trim().min(1).max(160),description:u.z.string().trim().max(1e3).optional(),source:me,action:pe,policy:he.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:u.z.string().datetime(),updatedAt:u.z.string().datetime()}).strict(),fe=u.z.object({type:u.z.literal("ai-session"),aiSessionId:u.z.string().trim().min(1).max(160)}).strict(),Ie=u.z.object({configHash:u.z.string().trim().min(8).max(80),deploymentId:u.z.string().trim().min(1).max(240).optional(),instanceId:u.z.string().trim().min(1).max(160),origin:u.z.enum(["control-plane","controlled-instance"]).default("controlled-instance"),enabled:u.z.boolean().default(!0),target:fe,localName:u.z.string().trim().min(1).max(160).optional(),createdAt:u.z.string().datetime(),updatedAt:u.z.string().datetime()}).strict(),ye=u.z.object({configHash:u.z.string().trim().min(8).max(80),deploymentId:u.z.string().trim().min(1).max(240).optional(),instanceId:u.z.string().trim().min(1).max(160),status:u.z.enum(["idle","running","disabled","error"]).default("idle"),lastTriggeredAt:u.z.string().datetime().optional(),lastCompletedAt:u.z.string().datetime().optional(),lastSkippedAt:u.z.string().datetime().optional(),lastError:u.z.string().trim().max(4e3).optional(),runCount:u.z.number().int().min(0).default(0),skippedCount:u.z.number().int().min(0).default(0)}).strict(),Ae=u.z.object({id:u.z.string().trim().min(1).max(160),configHash:u.z.string().trim().min(8).max(80),deploymentId:u.z.string().trim().min(1).max(240).optional(),instanceId:u.z.string().trim().min(1).max(160),eventType:u.z.enum(["manual","schedule","file-change","ai-session"]),status:u.z.enum(["started","completed","failed","skipped"]),target:fe,promptPreview:u.z.string().trim().max(500),eventSummary:u.z.string().trim().max(1e3).optional(),error:u.z.string().trim().max(4e3).optional(),startedAt:u.z.string().datetime(),completedAt:u.z.string().datetime().optional()}).strict();u.z.object({schemaVersion:u.z.literal(1).default(1),configs:u.z.array(ge).default([]),deployments:u.z.array(Ie).default([]),runtime:u.z.array(ye).default([]),recentRuns:u.z.array(Ae).default([])}).strict();const be="2026-07-27",we=u.z.string(),Ne=u.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),ze=u.z.string().datetime(),ve=u.z.record(u.z.string(),u.z.string()).default({}),Ee=u.z.record(u.z.string(),u.z.string()).default({}),Se=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,_e=/^sha256:([a-fA-F0-9]{64})$/,Te=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,ke=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function Ce(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 r=-1===n?void 0:t.slice(n+1),i=-1===n?t:t.slice(0,n),s=r?_e.exec(r):void 0;if(r&&!s)throw new Error("Docker image digest must use sha256 followed by 64 hexadecimal characters.");const o=i.lastIndexOf("/"),a=i.lastIndexOf(":"),c=a>o,d=c?i.slice(a+1):void 0,l=c?i.slice(0,a):i;if(d&&!Se.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!s)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const m=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),p=m?u.slice(1):u;if(m&&!Te.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!p.length||p.some(e=>!ke.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const h=u.map((e,t)=>m&&0===t?e.toLowerCase():e).join("/"),g=s?`sha256:${s[1].toLowerCase()}`:void 0;return`${h}${d?`:${d}`:""}${g?`@${g}`:""}`}const xe=u.z.string().trim().min(1).max(512).transform((e,t)=>{try{return Ce(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),u.z.NEVER}}),Oe=u.z.string().trim().transform((e,t)=>{const n=_e.exec(e);return n?`sha256:${n[1].toLowerCase()}`:(t.addIssue({code:"custom",message:"Docker image digest must use sha256 followed by 64 hexadecimal characters."}),u.z.NEVER)}),Re=u.z.object({codexModelHash:Ne.nullable().optional(),claudeModelHash:Ne.nullable().optional()}).strict().default({}),De=u.z.object({id:Ne,name:u.z.string().trim().min(1).max(120),kind:u.z.enum(["tty","gui","web"]),source:u.z.enum(["builtin","custom"]),availability:u.z.enum(["available","missing-dependency"]),capabilities:u.z.object({automation:u.z.enum(["cdp"]).optional(),supportsCwdSelection:u.z.boolean().default(!1)}).strict().default({supportsCwdSelection:!1}),diagnosticCode:u.z.enum(["APP_EXECUTABLE_NOT_FOUND"]).optional()}).strict(),je=u.z.object({code:u.z.enum(["APP_CATALOG_INVALID"]),message:u.z.string().trim().min(1).max(500)}).strict(),Pe=u.z.object({items:u.z.array(De).max(256),observedAt:ze,issues:u.z.array(je).max(32).default([])}).strict(),Me=u.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),Le=u.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),$e=u.z.enum(["apt","dnf","brew","npm"]),Fe=u.z.enum(["user","passwordless-sudo","root"]),Ue=u.z.object({platform:Me,arch:Le,installers:u.z.array($e).max(8),privilege:Fe,installerAccess:u.z.object({npmGlobalWritable:u.z.boolean().optional()}).strict().optional()}).strict(),Ve=u.z.enum(["installed","not-installed","broken","unsupported"]),He=u.z.enum(["recipe","bundled","external","none"]),qe=u.z.object({code:u.z.enum(["BUNDLED","EXTERNALLY_MANAGED","ALREADY_INSTALLED","NOT_INSTALLED","UNSUPPORTED_PLATFORM","INSTALLER_UNAVAILABLE","INSTALLER_NOT_WRITABLE","INSUFFICIENT_PRIVILEGE","OPERATION_IN_PROGRESS"]),message:u.z.string().trim().min(1).max(500)}).strict(),Be=u.z.object({id:Ne,name:u.z.string().trim().min(1).max(120),kind:u.z.enum(["tty","gui","web"]),description:u.z.string().trim().max(500).optional(),state:Ve,managementSource:He,version:u.z.string().trim().max(120).optional(),canInstall:u.z.boolean(),canUninstall:u.z.boolean(),installReason:qe.optional(),uninstallReason:qe.optional(),activeJobId:Ne.optional()}).strict(),Ke=u.z.enum(["install","uninstall"]),Ge=u.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),Je=u.z.object({current:u.z.number().finite().nonnegative().optional(),total:u.z.number().finite().positive().optional(),unit:u.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"]}),We=u.z.object({executable:u.z.string().trim().min(1).max(4096),args:u.z.array(u.z.string().max(4096)).max(128)}).strict(),Ye=u.z.object({code:u.z.string().trim().min(1).max(120).regex(/^[a-z0-9][a-z0-9._-]*$/),message:u.z.string().trim().min(1).max(4096),retryable:u.z.boolean(),sessionIds:u.z.array(Ne).max(64).optional()}).strict(),Xe=u.z.object({id:Ne,requestId:Ne.optional(),appId:Ne,operation:Ke,state:Ge,phase:u.z.string().trim().min(1).max(120).optional(),progress:Je.optional(),command:We.optional(),logTail:u.z.string().max(32768).optional(),logTruncated:u.z.boolean().optional(),error:Ye.optional(),requestedAt:ze,startedAt:ze.optional(),finishedAt:ze.optional(),updatedAt:ze}).strict(),Ze=u.z.object({streamId:Ne,sequence:u.z.number().int().nonnegative(),capabilities:Ue,apps:u.z.array(Be).max(256),activeJobs:u.z.array(Xe).max(256),recentJobs:u.z.array(Xe).max(256),observedAt:ze}).strict();u.z.object({requestId:Ne.optional()}).strict(),u.z.object({job:Xe}).strict(),u.z.object({type:u.z.literal("app-management"),streamId:Ne,sequence:u.z.number().int().nonnegative(),observedAt:ze,job:Xe.optional(),snapshot:Ze.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const Qe=u.z.object({component:u.z.enum(["control-plane","node-agent","controlled-instance"]),packageName:u.z.string().trim().max(160).optional(),packageVersion:u.z.string().trim().max(80).optional(),protocolVersion:we.optional(),buildId:u.z.string().trim().max(160).optional(),builtAt:u.z.string().trim().max(120).optional(),gitCommit:u.z.string().trim().max(120).optional(),imageRef:u.z.string().trim().max(512).optional(),imageDigest:u.z.string().trim().max(240).optional()}).strict(),et=u.z.enum(["stable","beta","alpha"]),tt=u.z.object({packageName:u.z.literal("@task-handoff/controlled-instance"),version:u.z.string().trim().min(1).max(80),platform:u.z.string().trim().min(1).max(40),arch:u.z.string().trim().min(1).max(40),formatVersion:u.z.number().int().positive(),launcherAbi:u.z.number().int().positive(),entrypoint:u.z.string().trim().min(1).max(512),sha256:u.z.string().regex(/^[a-f0-9]{64}$/)}).strict(),nt=u.z.object({code:u.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:u.z.string().trim().min(1).max(4096),expectedVersion:u.z.string().trim().min(1).max(80).optional(),actualVersion:u.z.string().trim().min(1).max(80).optional(),retryable:u.z.boolean().default(!1)}).strict(),rt=u.z.object({desiredVersion:u.z.string().trim().min(1).max(80),actualVersion:u.z.string().trim().min(1).max(80).optional(),phase:u.z.enum(["pending","draining","installing","restarting","verifying","matched","failed"]),attempt:u.z.number().int().nonnegative().default(0),lastAttemptAt:ze.optional(),matchedAt:ze.optional(),error:nt.optional()}).strict(),it=u.z.object({runningInstanceCount:u.z.number().int().nonnegative(),stoppedInstanceCount:u.z.number().int().nonnegative(),activeInstanceCount:u.z.number().int().nonnegative(),restartInstanceCount:u.z.number().int().nonnegative(),runningInstanceIds:u.z.array(Ne).max(1024).default([]),stoppedInstanceIds:u.z.array(Ne).max(1024).default([]),activeInstanceIds:u.z.array(Ne).max(1024).default([])}).strict(),st=u.z.object({phase:u.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),desiredVersion:u.z.string().trim().min(1).max(80),nodeVersion:u.z.string().trim().min(1).max(80).optional(),expectedInstanceIds:u.z.array(Ne).max(1024).default([]),expectedInstanceCount:u.z.number().int().nonnegative(),matchedInstanceCount:u.z.number().int().nonnegative(),pendingInstanceCount:u.z.number().int().nonnegative(),failedInstanceCount:u.z.number().int().nonnegative(),deferredInstanceCount:u.z.number().int().nonnegative().default(0)}).strict(),ot=u.z.object({channel:et.default("stable")}).strict(),at=u.z.object({source:u.z.literal("npm"),channel:et,currentVersion:u.z.string().trim().max(240).optional(),availableVersion:u.z.string().trim().min(1).max(240),artifactRef:u.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:u.z.array(tt).default([]),impact:it,updateAvailable:u.z.boolean(),supported:u.z.boolean().default(!0),reason:u.z.string().trim().max(2048).optional(),checkedAt:ze,preflightToken:u.z.string().trim().min(16).max(240).optional()}).strict(),ct=u.z.object({id:Ne,nodeId:Ne,source:u.z.literal("npm"),channel:et,fromVersion:u.z.string().trim().max(240).optional(),toVersion:u.z.string().trim().min(1).max(240),artifactRef:u.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:u.z.array(tt).default([]),impact:it,rollout:st,status:u.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:nt.optional(),startedAt:ze.optional(),completedAt:ze.optional(),createdAt:ze,updatedAt:ze}).strict(),dt=u.z.object({channel:et,targetVersion:u.z.string().trim().min(1).max(240),preflightToken:u.z.string().trim().min(16).max(240)}).strict(),lt=u.z.object({type:u.z.enum(["branch","tag","commit"]),name:u.z.string().trim().min(1).max(240).optional(),commit:u.z.string().trim().max(80).optional()}).strict(),ut=u.z.object({type:u.z.enum(["none","ssh-key","https-token"]).default("none"),secretId:u.z.string().trim().min(1).max(120).optional()}).strict(),mt=u.z.object({depth:u.z.number().int().positive().max(1e5).optional(),submodules:u.z.boolean().default(!1),lfs:u.z.boolean().default(!1),subdirectory:u.z.string().trim().max(240).default("")}).strict();u.z.object({id:Ne,name:u.z.string().trim().min(1).max(160),url:u.z.string().trim().min(1).max(2048),provider:u.z.string().trim().max(80).optional(),ref:lt.default({type:"branch",name:"main"}),auth:ut.default({type:"none"}),clone:mt.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageId:Ne.optional(),labels:ve,createdAt:ze,updatedAt:ze}).strict();const pt=u.z.object({id:Ne,nodeId:Ne,name:u.z.string().trim().min(1).max(160),path:u.z.string().trim().min(1).max(4096),defaultImageId:Ne.optional(),labels:ve,createdAt:ze,updatedAt:ze}).strict(),ht=u.z.discriminatedUnion("type",[u.z.object({type:u.z.literal("git-repository"),repositoryId:Ne.optional(),url:u.z.string().trim().min(1).max(2048),provider:u.z.string().trim().max(80).optional(),ref:lt.default({type:"branch",name:"main"}),auth:ut.default({type:"none"}),clone:mt.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),u.z.object({type:u.z.literal("git-template"),url:u.z.string().trim().min(1).max(2048),templateId:u.z.string().trim().min(1).max(120).optional(),ref:lt.default({type:"branch",name:"main"}),auth:ut.default({type:"none"}),clone:mt.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),u.z.object({type:u.z.literal("local-folder"),localFolderId:Ne.optional(),path:u.z.string().trim().min(1).max(4096),ownerNodeId:Ne.optional()}).strict()]),gt=u.z.object({mode:u.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]),path:u.z.string().trim().min(1).max(4096).default("/workspace"),volumeName:u.z.string().trim().max(240).optional(),readOnly:u.z.boolean().default(!1)}).strict(),ft=u.z.enum(["codex","claude"]),It=u.z.object({id:Ne,name:u.z.string().trim().min(1).max(160),source:ht,defaultImageId:Ne.optional(),defaultNodeId:Ne.optional(),defaultRuntimeId:Ne.optional(),workspacePolicy:gt,labels:ve,createdAt:ze,updatedAt:ze}).strict(),yt=u.z.object({id:Ne,name:u.z.string().trim().min(1).max(160),endpoint:u.z.string().trim().min(1).max(2048),key:u.z.string().trim().min(1).max(4096),model:u.z.string().trim().min(1).max(240),app:ft,enabled:u.z.boolean().default(!0),order:u.z.number().int().min(0).max(1e6).default(0),labels:ve,createdAt:ze,updatedAt:ze}).strict(),At=yt,bt=yt.omit({key:!0}).extend({keyPreview:u.z.string().trim().min(1).max(160),keySet:u.z.boolean()}).strict(),wt=bt.extend({referenceCount:u.z.number().int().min(0)}).strict(),Nt=u.z.object({instanceId:Ne,codexModelHash:Ne.optional(),claudeModelHash:Ne.optional(),updatedAt:ze}).strict(),zt=u.z.discriminatedUnion("type",[u.z.object({type:u.z.literal("control-plane"),name:yt.shape.name,enabled:yt.shape.enabled,order:yt.shape.order}).strict(),u.z.object({type:u.z.literal("node"),nodeId:Ne,name:yt.shape.name,enabled:yt.shape.enabled,order:yt.shape.order,referenceCount:u.z.number().int().min(0)}).strict()]),vt=u.z.object({id:Ne,model:bt,locations:u.z.array(zt).min(1),referenceCount:u.z.number().int().min(0).default(0)}).strict(),Et=u.z.object({nodeId:Ne,code:u.z.string().trim().min(1).max(120),message:u.z.string().trim().min(1).max(2e3)}).strict();u.z.object({models:u.z.array(vt),nodeDiagnostics:u.z.array(Et).default([]),updatedAt:ze}).strict();const St=yt.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),_t=St.partial().strict(),Tt=yt,kt=u.z.object({modelSelection:Re,codexModelHash:Ne.optional(),claudeModelHash:Ne.optional()}).strict();function Ct(e){const t={app:ft.parse(e.app),endpoint:yt.shape.endpoint.parse(e.endpoint),key:yt.shape.key.parse(e.key),model:yt.shape.model.parse(e.model)};return`mdl_${m.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const xt=u.z.object({id:Ne,name:u.z.string().trim().min(1).max(160),reference:xe,pullPolicy:u.z.literal("if-not-present").default("if-not-present"),capabilities:u.z.array(u.z.string().trim().min(1).max(80)).default([]),optionalApps:u.z.array(u.z.string().trim().min(1).max(120)).default([]),defaultEnv:Ee,labels:ve,createdAt:ze,updatedAt:ze}).strict(),Ot=xt.omit({reference:!0}).extend({requestedReference:xe,resolvedDigest:Oe.optional(),resolvedReference:xe.optional()}).strict(),Rt=u.z.object({phase:u.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:xe,generation:u.z.number().int().nonnegative().default(0),error:u.z.string().trim().max(4096).optional(),startedAt:ze,updatedAt:ze}).strict(),Dt="image.pull.terminal.output",jt="image.pull.terminal.finished",Pt=u.z.object({instanceId:Ne,generation:u.z.number().int().nonnegative(),requestedReference:xe,sequence:u.z.number().int().nonnegative(),observedAt:ze}).strict(),Mt=Pt.extend({data:u.z.string().min(1).max(65536),replay:u.z.boolean().optional()}).strict(),Lt=Pt.extend({outcome:u.z.enum(["succeeded","failed"])}).strict();Pt.extend({status:u.z.enum(["connecting","pulling","extracting","complete","failed"]),layers:u.z.object({total:u.z.number().int().nonnegative(),completed:u.z.number().int().nonnegative(),downloaded:u.z.number().int().nonnegative(),downloading:u.z.number().int().nonnegative(),extracting:u.z.number().int().nonnegative()}).strict(),bytes:u.z.object({current:u.z.number().finite().nonnegative(),total:u.z.number().finite().positive()}).strict().optional(),percent:u.z.number().finite().min(0).max(100).optional(),message:u.z.string().trim().min(1).max(500),terminalTail:u.z.string().max(262144).optional(),terminalTruncated:u.z.boolean().optional()}).strict();const $t=u.z.object({id:Ne,name:u.z.string().trim().min(1).max(160),connectionMode:u.z.enum(["local-ipc","local-loopback","direct-http","reverse-wss"]).default("direct-http"),auth:u.z.object({mode:u.z.enum(["local-static-key","paired-hmac"]).default("local-static-key"),keyId:Ne.optional(),secret:u.z.string().trim().max(4096).optional(),pairedAt:ze.optional(),pairing:u.z.object({status:u.z.enum(["pending","paired","expired"]).default("pending"),joinToken:u.z.string().trim().max(4096).optional(),expiresAt:ze.optional()}).strict().optional()}).strict().default({mode:"local-static-key"}),endpoint:u.z.string().trim().max(2048).optional(),controlEndpoint:u.z.string().trim().max(2048).optional(),containerEndpoint:u.z.string().trim().max(2048).optional(),publicWebBase:u.z.string().trim().max(2048).optional(),status:u.z.enum(["unknown","online","offline","degraded"]).default("unknown"),health:u.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),capabilities:u.z.record(u.z.string(),u.z.unknown()).default({}),appInventory:Pe.optional(),labels:ve,lastSeenAt:ze.optional(),createdAt:ze,updatedAt:ze}).strict(),Ft=u.z.object({id:Ne,nodeId:Ne,name:u.z.string().trim().min(1).max(160),type:u.z.enum(["docker","kubernetes","local"]),status:u.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:u.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),capabilities:u.z.record(u.z.string(),u.z.unknown()).default({}),labels:ve,createdAt:ze,updatedAt:ze}).strict(),Ut=u.z.object({instanceId:Ne,runtimeKind:u.z.literal("docker"),state:u.z.enum(["pending","available","stopped","unavailable"]),sampledAt:ze,cpu:u.z.object({usagePercent:u.z.number().nonnegative()}).strict().optional(),memory:u.z.object({usageBytes:u.z.number().nonnegative(),limitBytes:u.z.number().nonnegative().optional(),usagePercent:u.z.number().nonnegative().optional()}).strict().optional(),network:u.z.object({rxBytes:u.z.number().nonnegative(),txBytes:u.z.number().nonnegative()}).strict().optional(),blockIo:u.z.object({readBytes:u.z.number().nonnegative(),writeBytes:u.z.number().nonnegative()}).strict().optional(),pids:u.z.number().int().nonnegative().optional(),error:u.z.string().trim().max(2048).optional()}).strict();u.z.object({ok:u.z.boolean().optional(),role:u.z.string().optional(),nodeId:Ne.optional(),platform:Me.optional()}).passthrough();const Vt=u.z.object({bindScope:u.z.enum(["loopback","all-ipv4"]),port:u.z.number().int().min(1).max(65535)}).strict(),Ht=Vt.extend({host:u.z.enum(["127.0.0.1","0.0.0.0"]),status:u.z.enum(["listening","error"]),source:u.z.enum(["bootstrap","persisted"]),error:u.z.string().trim().max(2048).optional()}).strict(),qt=Vt;u.z.object({nodeId:Ne,joinToken:u.z.string().trim().min(1),expiresAt:ze}).passthrough(),u.z.object({id:Ne,keyId:Ne,url:u.z.string().trim().min(1).max(2048).optional(),name:u.z.string().trim().min(1).max(160).optional(),pairedAt:ze,updatedAt:ze.optional(),active:u.z.boolean().optional(),current:u.z.boolean().optional()}).passthrough(),u.z.object({remote:u.z.object({id:Ne,url:u.z.string().trim().min(1).max(2048).optional(),keyId:Ne,pairedAt:ze,active:u.z.boolean()}).passthrough(),tunnel:u.z.object({status:u.z.enum(["disabled","saved","connecting","connected","failed"]),error:u.z.string().trim().max(2048).optional()}).passthrough()}).passthrough(),u.z.object({deleted:u.z.boolean().optional()}).passthrough();const Bt=u.z.object({repository:u.z.string().trim().optional(),tag:u.z.string().trim().optional(),id:u.z.string().trim(),createdSince:u.z.string().trim().optional(),size:u.z.string().trim().optional(),reference:u.z.string().trim().min(1),repoDigests:u.z.array(u.z.string().trim().min(1).max(512)).default([])}).passthrough();u.z.object({image:xt,status:u.z.enum(["available","pull-required","unknown"]),localImage:Bt.optional(),error:u.z.string().trim().max(2048).optional()}).strict();const Kt=u.z.lazy(()=>u.z.object({name:u.z.string().trim().min(1),path:u.z.string().trim().min(1).max(4096),children:u.z.array(Kt)}).passthrough());u.z.object({status:u.z.number().int().min(100).max(599).optional(),headers:u.z.record(u.z.string(),u.z.string()).optional(),bodyBase64:u.z.string().optional()}).passthrough();const Gt=u.z.object({strategy:u.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),web:u.z.string().trim().max(2048).optional(),api:u.z.string().trim().max(2048).optional(),vnc:u.z.string().trim().max(2048).optional(),tty:u.z.string().trim().max(2048).optional(),logs:u.z.string().trim().max(2048).optional(),status:u.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict(),Jt=u.z.object({strategy:u.z.enum(["control-plane-proxy","direct-port","node-proxy","kubernetes-ingress","kubernetes-port-forward"]).default("control-plane-proxy"),web:u.z.string().trim().max(2048).optional(),api:u.z.string().trim().max(2048).optional(),ws:u.z.string().trim().max(2048).optional(),status:u.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict().default({strategy:"control-plane-proxy",status:"unknown"}),Wt=u.z.object({mode:u.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]).optional(),status:u.z.enum(["unknown","pending","ready","failed"]).default("unknown"),path:u.z.string().trim().max(4096).optional(),resolvedCommit:u.z.string().trim().max(120).optional(),error:u.z.string().trim().max(2048).optional()}).passthrough(),Yt=u.z.object({id:Ne,name:u.z.string().trim().min(1).max(160),projectId:Ne.optional(),source:ht,sourceSnapshot:u.z.record(u.z.string(),u.z.unknown()).default({}),modelSelection:Re,nodeId:Ne,runtimeId:Ne,imageId:Ne.optional(),imageSnapshot:Ot.optional(),imageProvisioning:Rt.optional(),stateRevision:u.z.number().int().min(0).default(0),status:u.z.enum(["created","provisioning","starting","registering","registered","running","stopping","stopped","failed","unhealthy"]).default("created"),health:u.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),connectionStatus:u.z.enum(["unknown","online","offline","endpoint-unreachable"]).default("unknown"),agentStatus:u.z.enum(["unknown","online","offline"]).default("unknown"),targetStatus:u.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),uiAccessStatus:u.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),controlMode:u.z.enum(["standalone","controlled"]).default("controlled"),protocolVersion:we.optional(),instanceVersion:u.z.string().trim().max(80).optional(),build:Qe.optional(),runtimeVersion:rt.optional(),ready:u.z.boolean().default(!1),capabilities:u.z.record(u.z.string(),u.z.unknown()).default({}),appInventory:Pe.optional(),config:u.z.object({autoImportAgentConfigs:u.z.boolean().default(!0),defaultCodexPermissionMode:L.default("ask")}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"}),workspace:Wt.default({status:"unknown"}),target:Gt.default({strategy:"direct-port",status:"unknown"}),access:Jt,apps:u.z.object({runningCount:u.z.number().int().min(0).default(0),problemCount:u.z.number().int().min(0).default(0),updatedAt:ze.optional(),revision:u.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:ne.default(()=>({runningCount:0,waitingCount:0,staleCount:0,sessions:[],updatedAt:(new Date).toISOString()})),triggers:u.z.object({enabledCount:u.z.number().int().min(0).default(0),runningCount:u.z.number().int().min(0).default(0),errorCount:u.z.number().int().min(0).default(0),configs:u.z.array(u.z.object({configHash:u.z.string().trim().min(1),config:ge,deployments:u.z.array(Ie).default([]),runtime:u.z.array(ye).default([])}).strict()).default([]),recentRuns:u.z.array(Ae).default([])}).strict().optional(),runtime:u.z.object({kind:u.z.string().trim().max(80).optional(),containerName:u.z.string().trim().max(240).optional(),containerId:u.z.string().trim().max(240).optional(),workspacePath:u.z.string().trim().max(4096).optional(),pid:u.z.number().int().positive().optional(),port:u.z.number().int().positive().max(65535).optional(),labels:u.z.record(u.z.string(),u.z.string()).default({})}).strict().default({labels:{}}),registrationToken:u.z.string().trim().min(1).max(240).optional(),lastHeartbeatAt:ze.optional(),createdAt:ze,updatedAt:ze}).strict(),Xt="instance.lifecycle.snapshot",Zt=u.z.object({instanceId:Yt.shape.id,revision:u.z.number().int().min(0),updatedAt:ze,status:Yt.shape.status.unwrap(),health:Yt.shape.health.unwrap(),connectionStatus:Yt.shape.connectionStatus.unwrap(),accessStatus:u.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:Rt.optional(),workspace:Wt,runtime:Yt.shape.runtime.unwrap(),runtimeVersion:rt.optional(),ready:u.z.boolean(),lastHeartbeatAt:ze.optional()}).strict();function Qt(e,t){return Yt.safeParse(en(e,t))}function en(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,r=new Set(Object.keys(Yt.shape)),i={};for(const[e,s]of Object.entries(n))r.has(e)?i[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),i.capabilities=e}else i.capabilities={};i.appInventory=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e;Object.keys(r).some(e=>!["observedAt","items","issues"].includes(e))&&t?.({instanceId:n,field:"appInventory"});const i={observedAt:r.observedAt,items:Array.isArray(r.items)?r.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 r=rn(e,["id","name","kind","source","availability","diagnosticCode"]);return!r||"object"!=typeof r||Array.isArray(r)?r:{...r,capabilities:rn(e.capabilities,["automation","supportsCwdSelection"])}}):r.items,issues:Array.isArray(r.issues)?r.issues.map(e=>rn(e,["code","message"])):r.issues},s=Pe.safeParse(i);return s.success?s.data:void 0}(n.appInventory,t,"string"==typeof n.id?n.id:void 0),i.source=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return e;const r=e,i=r.type,s=ht.options.find(e=>e.shape.type.value===i);if(!s)return e;const o="local-folder"===i?["type","localFolderId","path","ownerNodeId"]:"git-template"===i?["type","url","templateId","ref","auth","clone"]:["type","repositoryId","url","provider","ref","auth","clone"],a=rn(r,o);if("local-folder"!==i){const e=tn(lt,rn(r.ref,["type","name","commit"]),"source.ref",t,n),i=tn(ut,rn(r.auth,["type","secretId"]),"source.auth",t,n),s=tn(mt,rn(r.clone,["depth","submodules","lfs","subdirectory"]),"source.clone",t,n);e?a.ref=e:delete a.ref,i?a.auth=i:delete a.auth,s?a.clone=s:delete a.clone}const c=tn(s,a,"source",t,n);return c?(Object.keys(r).some(e=>!o.includes(e))&&t?.({instanceId:n,field:"source"}),c):a}(n.source,t,"string"==typeof n.id?n.id:void 0),i.sourceSnapshot=n.sourceSnapshot&&"object"==typeof n.sourceSnapshot&&!Array.isArray(n.sourceSnapshot)?n.sourceSnapshot:{},i.build=tn(Qe,n.build,"build",t,"string"==typeof n.id?n.id:void 0),i.aiSessions=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,i=Array.isArray(r.sessions)?r.sessions.flatMap((e,r)=>{const i=tn(te,e,`aiSessions.sessions.${r}`,t,n);return i?[i]:[]}):[],s={runningCount:"number"==typeof r.runningCount&&Number.isInteger(r.runningCount)&&r.runningCount>=0?r.runningCount:0,waitingCount:"number"==typeof r.waitingCount&&Number.isInteger(r.waitingCount)&&r.waitingCount>=0?r.waitingCount:0,staleCount:"number"==typeof r.staleCount&&Number.isInteger(r.staleCount)&&r.staleCount>=0?r.staleCount:0,sessions:i,updatedAt:ze.safeParse(r.updatedAt).success?r.updatedAt:(new Date).toISOString()};return Object.keys(r).some(e=>!["runningCount","waitingCount","staleCount","sessions","updatedAt"].includes(e))&&t?.({instanceId:n,field:"aiSessions"}),ne.parse(s)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),i.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e;Object.keys(r).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const i=(e,r,i)=>Array.isArray(e)?e.flatMap((e,s)=>{const o=tn(r,e,`${i}.${s}`,t,n);return o?[o]:[]}):[],s=Array.isArray(r.configs)?r.configs.flatMap((e,r)=>{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.${r}`});const o=function(e,t,n,r){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e,s=rn(i,["configHash","name","description","createdAt","updatedAt"]);if(i.source&&"object"==typeof i.source&&!Array.isArray(i.source)){const e=i.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=rn(e,t)}return s.action=rn(i.action,["promptTemplate"]),s.policy=rn(i.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),tn(ge,s,t,n,r)}(s.config,`triggers.configs.${r}.config`,t,n);return"string"==typeof s.configHash&&o?[{configHash:s.configHash,config:o,deployments:i(s.deployments,Ie,`triggers.configs.${r}.deployments`),runtime:i(s.runtime,ye,`triggers.configs.${r}.runtime`)}]:[]}):[];return{enabledCount:"number"==typeof r.enabledCount&&Number.isInteger(r.enabledCount)&&r.enabledCount>=0?r.enabledCount:0,runningCount:"number"==typeof r.runningCount&&Number.isInteger(r.runningCount)&&r.runningCount>=0?r.runningCount:0,errorCount:"number"==typeof r.errorCount&&Number.isInteger(r.errorCount)&&r.errorCount>=0?r.errorCount:0,configs:s,recentRuns:i(r.recentRuns,Ae,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),i.apps=tn(Yt.shape.apps.unwrap(),rn(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},i.config=tn(Yt.shape.config.unwrap(),rn(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"},i.modelSelection=tn(Re.unwrap(),rn(n.modelSelection,["codexModelHash","claudeModelHash"]),"modelSelection",t,"string"==typeof n.id?n.id:void 0)||{},i.imageSnapshot=function(e,t,n,r){if(!e||"object"!=typeof e||Array.isArray(e))return e;const i=e,s=function(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=("string"==typeof t.id&&t.id,"string"==typeof t.image?t.image:void 0);Object.prototype.hasOwnProperty.call(t,"registry");let r="string"==typeof t.reference?t.reference:n;if(r)try{r=Ce(r)}catch{if(!r.includes("@")&&r.lastIndexOf(":")<=r.lastIndexOf("/"))try{r=Ce(`${r}:latest`)}catch{}}return{id:t.id,name:t.name,reference:r,pullPolicy:t.pullPolicy??"if-not-present",capabilities:t.capabilities,optionalApps:t.optionalApps,defaultEnv:t.defaultEnv,labels:t.labels,createdAt:t.createdAt,updatedAt:t.updatedAt}}(i),{reference:o,...a}=s,c=i.requestedReference??o;return void 0===i.image&&void 0===i.reference||n?.({instanceId:r,field:"imageSnapshot.reference"}),{...a,id:i.id??t,requestedReference:c,resolvedDigest:i.resolvedDigest,resolvedReference:i.resolvedReference}}(n.imageSnapshot,n.imageId,t,"string"==typeof n.id?n.id:void 0),i.imageProvisioning=tn(Rt,rn(n.imageProvisioning,["phase","requestedReference","generation","error","startedAt","updatedAt"]),"imageProvisioning",t,"string"==typeof n.id?n.id:void 0),i.runtimeVersion=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const r=e,i=e=>{if("string"!=typeof e)return;const t=e.trim();return t&&t.length<=80?t:void 0},s=i(r.desiredVersion);if(!s)return void t?.({instanceId:n,field:"runtimeVersion.desiredVersion"});const o=new Set(rt.shape.phase.options),a="string"==typeof r.phase?r.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"}),r.error&&"object"==typeof r.error&&!Array.isArray(r.error)){const e=r.error,s="string"==typeof e.message?e.message.trim().slice(0,4096):"";if(s){const r=new Set(nt.shape.code.options),o="string"==typeof e.code&&r.has(e.code)?e.code:"INSTANCE_RUNTIME_INSTALL_FAILED";o!==e.code&&t?.({instanceId:n,field:"runtimeVersion.error.code"});const a=i(e.expectedVersion),c=i(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 r.error&&r.error.trim()&&(d={code:"INSTANCE_RUNTIME_INSTALL_FAILED",message:r.error.trim().slice(0,4096),expectedVersion:s,...i(r.actualVersion)?{actualVersion:i(r.actualVersion)}:{},retryable:!1});const l=i(r.actualVersion),u=ze.safeParse(r.lastAttemptAt),m=ze.safeParse(r.matchedAt);return void 0===r.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===r.matchedAt||m.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:s,...l?{actualVersion:l}:{},phase:c,attempt:"number"==typeof r.attempt&&Number.isInteger(r.attempt)&&r.attempt>=0?r.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),i.workspace=tn(Wt,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},i.runtime=tn(Yt.shape.runtime.unwrap(),rn(n.runtime,["kind","containerName","containerId","workspacePath","pid","port","labels"]),"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},i.target=tn(Gt,rn(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"},i.access=tn(Jt,rn(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,r]of Object.entries(Yt.shape))Object.prototype.hasOwnProperty.call(i,e)&&!r.safeParse(i[e]).success&&r.safeParse(void 0).success&&(delete i[e],t?.({instanceId:"string"==typeof n.id?n.id:void 0,field:e}));return i}function tn(e,t,n,r,i){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&&r?.({instanceId:i,field:n}),t.data;let a=!1;for(const e of t.error.issues){if("unrecognized_keys"!==e.code)continue;const t=nn(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=nn(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 r?.({instanceId:i,field:n}),t.data}break}}r?.({instanceId:i,field:n})}function nn(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function rn(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 sn=u.z.object({instanceId:Ne.optional(),name:u.z.string().trim().min(1).max(160),projectId:Ne.optional(),source:ht.optional(),nodeId:Ne.optional(),runtimeId:Ne.optional(),imageId:Ne.optional(),instanceVersion:u.z.string().trim().max(80).optional(),protocolVersion:we,build:Qe.optional(),controlMode:u.z.enum(["standalone","controlled"]).default("controlled"),capabilities:u.z.record(u.z.string(),u.z.unknown()).default({}),appInventory:Pe.optional(),target:Gt.default({strategy:"direct-port",status:"unknown"}),workspace:Wt.default({status:"unknown"}),registrationToken:u.z.string().trim().max(240).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==be||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),on=u.z.object({status:Yt.shape.status.optional(),health:Yt.shape.health.optional(),protocolVersion:we,build:Qe.optional(),capabilities:Yt.shape.capabilities.optional(),appInventory:Pe.optional(),apps:Yt.shape.apps.optional(),aiSessions:Yt.shape.aiSessions.optional(),triggers:Yt.shape.triggers.optional(),workspace:Wt.optional(),target:Gt.partial().optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==be||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),an=u.z.enum(["web","telegram","wechat","dingding"]);function cn(e){return e.readyState===(e.OPEN??1)}function dn(e,t,n){e.close(function(e){if("number"==typeof e&&Number.isInteger(e))return e>=3e3&&e<=4999||e>=1e3&&e<=1014&&1004!==e&&1005!==e&&1006!==e?e:void 0}(t),function(e){const t=Buffer.isBuffer(e)?e.toString("utf8"):"string"==typeof e?e:"";if(Buffer.byteLength(t,"utf8")<=123)return t;let n="";for(const e of t){const t=`${n}${e}`;if(Buffer.byteLength(t,"utf8")>123)break;n=t}return n}(n)||void 0)}function ln(e,t){e.send(t.data,{binary:t.isBinary})}function un(e,t){if(cn(e))for(const n of t.splice(0))ln(e,n)}function mn(e,t,n={}){return new Promise((r,i)=>{const s=o.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),a=[],c=[];let d=!1;const l=n.timeoutMs?setTimeout(()=>{d=!0,s.kill("SIGKILL")},n.timeoutMs):void 0;l?.unref?.(),s.stdout.on("data",e=>a.push(Buffer.from(e))),s.stderr.on("data",e=>c.push(Buffer.from(e))),s.on("error",e=>{l&&clearTimeout(l),i(e)}),s.on("close",t=>{l&&clearTimeout(l);const s={stdout:Buffer.concat(a).toString("utf8").trim(),stderr:Buffer.concat(c).toString("utf8").trim()};if(d){const t=new Error(`${e} timed out after ${n.timeoutMs}ms`);return Object.assign(t,{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:s}),void i(t)}if(0===t)return void r(s);const o=new Error(s.stderr||`${e} exited with code ${t}`);Object.assign(o,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s}),i(o)})})}u.z.object({id:Ne,channel:an,name:u.z.string().trim().min(1).max(160),enabled:u.z.boolean().default(!1),token:u.z.string().trim().max(4096).optional(),defaultChatId:u.z.string().trim().max(240).optional(),allowedUserIds:u.z.array(u.z.string().trim().min(1).max(240)).default([]),pollIntervalMs:u.z.number().int().positive().max(6e4).default(3e3),settings:u.z.record(u.z.string(),u.z.unknown()).default({}),createdAt:ze,updatedAt:ze}).strict(),u.z.object({id:Ne,channel:an,bridgeId:Ne.optional(),chatSessionId:u.z.string().trim().min(1).max(240),userId:u.z.string().trim().max(240).optional(),activeProjectId:Ne.optional(),activeInstanceId:Ne.optional(),activeAiSessionId:u.z.string().trim().min(1).max(120).optional(),lastUsedAt:ze,createdAt:ze,updatedAt:ze}).strict(),u.z.object({source:u.z.object({type:u.z.literal("chat-gateway").default("chat-gateway"),channel:an,bridgeId:Ne.optional(),chatSessionId:u.z.string().trim().min(1).max(240),userId:u.z.string().trim().max(240).optional()}).strict(),message:u.z.object({text:u.z.string().trim().max(2e4).default(""),attachments:u.z.array(D).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>w&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),target:u.z.object({instanceId:Ne,aiSessionId:u.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),u.z.object({id:Ne,instanceId:Ne,projectId:Ne.optional(),aiSessionId:u.z.string().trim().min(1).max(120),providerSessionId:u.z.string().trim().max(240).optional(),result:u.z.string().default(""),timeoutMs:u.z.number().positive().optional(),source:u.z.string().trim().max(120).optional(),kind:u.z.enum(["task","approval"]).default("task"),status:u.z.enum(["pending","unreachable"]).default("pending"),error:u.z.string().trim().max(2048).optional(),lastSeenAt:ze}).strict();const pn=(e,t,n={})=>new Promise((r,i)=>{const s=[];let o,a=!1;try{o=p.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void i(e)}const c=n.timeoutMs?setTimeout(()=>{a=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;c?.unref?.(),o.onData(e=>{s.push(e),n.onData?.(e)}),o.onExit(({exitCode:t})=>{c&&clearTimeout(c);const o={stdout:s.join(""),stderr:""};a?i(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o})):0!==t?i(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})):r(o)})});class hn{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=mn,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===mn?pn:async(t,n,r={})=>{const i=await e(t,n,{timeoutMs:r.timeoutMs});return i.stdout&&r.onData?.(i.stdout),i.stderr&&r.onData?.(i.stderr),i}}(e)}ensure(e,t,n){const r=Ce(e),i=this.inFlight.get(r);if(i)return t&&(i.phaseListeners.add(t),i.phase&&t(i.phase)),n&&(i.terminalListeners.add(n),i.terminalTail&&n({sequence:i.terminalSequence,data:i.terminalTail,replay:!0})),i.promise;const s=new Set,o=new Set;t&&s.add(t),n&&o.add(n);const a={promise:Promise.resolve(void 0),phaseListeners:s,terminalListeners:o,terminalSequence:0,terminalTail:""};return a.promise=this.ensureOnce(r,e=>{a.phase=e,s.forEach(t=>t(e))},e=>{a.terminalSequence+=1,a.terminalTail=`${a.terminalTail}${e}`.slice(-262144);const t={sequence:a.terminalSequence,data:e};o.forEach(e=>e(t))}).finally(()=>this.inFlight.delete(r)),this.inFlight.set(r,a),a.promise}async ensureOnce(e,t,n){t("checking-image");let r=await this.inspect(e).catch(()=>{}),i=!1;r||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,onData:n}),i=!0,r=await this.inspect(e)),t("resolving-image");const s=(o=r,Array.isArray(o.RepoDigests)?o.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var o;const a=s?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...a?{resolvedDigest:a}:{},resolvedReference:s||e,pulled:i}}async inspect(e){const t=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"]);return JSON.parse(t.stdout.trim()||"{}")}}class gn{runCommand;publishHost;images;launcherAssetsDir;constructor(e=mn,r={}){this.runCommand=e,this.images=r.imageService||new hn(e),this.publishHost=r.publishHost||"127.0.0.1",this.launcherAssetsDir=r.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(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,r=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return r.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||r[0]}()}async start(e){bn(e);const t=e.instance.runtime.containerName||An(e.instance.id);if(await this.runCommand("docker",["start",t]).catch(()=>{}))return this.runningResult(e,t,e.instance.runtime.containerId);await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);const n=await this.runCommand("docker",function(e,t,n={}){const r=n.publishHost||"127.0.0.1",i=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=${i}`,"--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",`${r}::8080`,"-e","TASK_HANDOFF_CONTROL_MODE=controlled","-e",`TASK_HANDOFF_NODE_AGENT_URL=${e.nodeAgentUrl||e.node?.endpoint||""}`,"-e",`TASK_HANDOFF_INSTANCE_ID=${e.instance.id}`,"-e",`TASK_HANDOFF_INSTANCE_NAME=${e.instance.name}`,"-e",`TASK_HANDOFF_REGISTRATION_TOKEN=${e.instance.registrationToken||""}`,"-e",`TASK_HANDOFF_PROJECT_ID=${e.project.id}`,"-e",`TASK_HANDOFF_NODE_ID=${i}`,"-e",`TASK_HANDOFF_RUNTIME_ID=${s}`,"-e",`TASK_HANDOFF_IMAGE_ID=${e.image.id}`,"-e","TASK_HANDOFF_CHAT_BRIDGES=none","-e",`TASK_HANDOFF_WORKSPACE=${e.project.workspacePolicy.path||"/workspace"}`,"-e",`TASK_HANDOFF_WORKSPACE_MODE=${e.project.workspacePolicy.mode}`];"local-folder"===e.project.source.type?o.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(o.push("-e",`TASK_HANDOFF_PROJECT_SOURCE=${JSON.stringify(e.project.source)}`),o.push("-e",`TASK_HANDOFF_WORKSPACE_POLICY=${JSON.stringify(e.project.workspacePolicy)}`),o.push("-e",`TASK_HANDOFF_GIT_URL=${e.project.source.url}`),e.project.source.ref?.commit?o.push("-e",`TASK_HANDOFF_GIT_COMMIT=${e.project.source.ref.commit}`):e.project.source.ref?.name&&o.push("-e",`TASK_HANDOFF_GIT_REF=${e.project.source.ref.name}`),e.project.source.clone?.depth&&o.push("-e",`TASK_HANDOFF_GIT_DEPTH=${e.project.source.clone.depth}`),o.push("-e","TASK_HANDOFF_GIT_SUBMODULES="+(e.project.source.clone?.submodules?"true":"false")),o.push("-e","TASK_HANDOFF_GIT_LFS="+(e.project.source.clone?.lfs?"true":"false")),e.project.source.clone?.subdirectory&&o.push("-e",`TASK_HANDOFF_WORKSPACE_SUBDIRECTORY=${e.project.source.clone.subdirectory}`));for(const[t,n]of Object.entries(e.image.defaultEnv))o.push("-e",`${t}=${n}`);for(const[t,n]of Object.entries(e.modelEnv||{}))o.push("-e",`${t}=${n}`);return o.push(e.image.resolvedReference||e.image.requestedReference),o}(e,t,{publishHost:this.publishHost}));return this.runningResult(e,t,n.stdout||void 0)}async runningResult(e,t,n){const r=await this.containerPort(t,"8080/tcp"),i=r?`http://127.0.0.1:${r}`:void 0,s=e.node?.id||"node_unset",o=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:i?"online":"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:i?"reachable":"unknown",...i?{web:i,api:`${i}/api`}:{}},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":s,"task-handoff.runtime-id":o,"task-handoff.image-id":e.image.id}}}}async stop(e){return await this.runCommand("docker",["stop",e.instance.runtime.containerName||An(e.instance.id)]).catch(()=>({stdout:"",stderr:""})),{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e,t){bn(e);const n=e.instance.runtime.containerName||An(e.instance.id),r=await this.inspectContainerId(n);if(!r)throw fn("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);In(n,r,t,"before restart","INSTANCE_RUNTIME_RESTART_FAILED"),await this.runCommand("docker",["restart",n]);const i=await this.inspectContainerId(n);if(!i||i!==r)throw fn("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return In(n,i,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,i)}async delete(e){return await this.runCommand("docker",["rm","-f",e.instance.runtime.containerName||An(e.instance.id)]).catch(()=>({stdout:"",stderr:""})),{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async installRuntime(e){const t=await this.installRuntimeRelease(e);In(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",e.containerName])}catch(t){throw fn("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw fn("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return In(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 fn("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);In(e.containerName,t,e.expectedContainerId,"before runtime install","INSTANCE_RUNTIME_INSTALL_FAILED");const n=`/opt/task-handoff/instance-runtime/incoming/task-handoff-runtime-${r=e.identity.version,r.replace(/[^0-9A-Za-z.+_-]/g,"-")}-${e.identity.sha256.slice(0,12)}.tar.gz`;var r;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 fn("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 i=await this.inspectContainerId(e.containerName);if(!i||i!==t)throw fn("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return In(e.containerName,i,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 r=await this.runCommand("docker",["inspect","--format","{{json .}}",e]).then(e=>JSON.parse(e.stdout.trim()||"{}")).catch(()=>{});if(t=r?.Platform,"string"==typeof r?.Image&&r.Image){const e=await this.runCommand("docker",["image","inspect","--format","{{json .}}",r.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 fn("INSTANCE_BASE_RUNTIME_INCOMPATIBLE","Could not inspect the Docker runtime target.",e)});t||=e.OSType,n||=e.Architecture}const r="linux"===(i=t)||"darwin"===i?i:"windows"===i||"win32"===i?"win32":void 0;var i;const s=function(e){return"amd64"===e||"x86_64"===e||"x64"===e?"x64":"arm64"===e||"aarch64"===e?"arm64":void 0}(n);if(!r||!s)throw fn("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:r,arch:s,launcherAbi:1}}async rollbackRuntime(e){const t=await this.inspectContainerId(e);if(!t)throw fn("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${e} does not exist.`);try{await this.runCommand("docker",["exec","--user","0",e,"task-handoff-runtime","rollback"]),await this.runCommand("docker",["restart",e])}catch(t){throw fn("INSTANCE_RUNTIME_RESTART_FAILED",`Could not roll back ${e} to its previous controlled-instance release.`,t)}const n=await this.inspectContainerId(e);if(!n||n!==t)throw fn("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while rolling back ${e}.`);return this.inspectRuntimeVersion(e)}async bootstrapLegacyLauncher(e){const t=await this.inspectContainerId(e);if(!t)throw fn("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container ${e} does not exist.`);if(await this.runCommand("docker",["exec",e,"test","-x","/usr/local/bin/task-handoff-runtime"]).then(()=>!0).catch(()=>!1))return{migrated:!1,containerId:t,audit:{operation:"legacy-launcher-bootstrap",rootExec:!1,subsequentInstallUser:"root"}};const r=[[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 r)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 fn("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not bootstrap the stable runtime launcher in ${e}.`,t)}if(await this.inspectContainerId(e)!==t)throw fn("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while bootstrapping ${e}.`);return{migrated:!0,containerId:t,audit:{operation:"legacy-launcher-bootstrap",rootExec:!0,subsequentInstallUser:"root"}}}async inspectContainerId(e){const t=await this.runCommand("docker",["inspect","--format","{{.Id}}",e]).catch(()=>{});return t?.stdout.trim()||void 0}async containerPort(e,t){const n=(await this.runCommand("docker",["port",e,t]).catch(()=>({stdout:"",stderr:""}))).stdout.split(/\r?\n/).find(Boolean),r=n?.match(/:(\d+)$/);return r?.[1]}}function fn(e,t,n){const r=function(e){if(!e||"object"!=typeof e)return void 0===e?void 0:String(e);const t=e,n=t.details?.stderr||t.details?.stdout;return"string"==typeof n&&n.trim()?n.trim():"string"==typeof t.message&&t.message.trim()?t.message.trim():void 0}(n),i=new Error(r?`${t} Cause: ${r}`:t,void 0===n?void 0:{cause:n});return Object.assign(i,{statusCode:502,code:e}),i}function In(e,t,n,r,i){if(n&&t!==n)throw fn(i,`Docker container ${e} identity mismatch ${r}: expected ${n}, got ${t}.`)}async function yn(e=mn){return async function(e=mn){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>",r=t.Tag||"<none>",i=t.ID||t.IDShort||"",s="<none>"!==n&&"<none>"!==r?`${n}:${r}`:i,o="<none>"!==n&&t.Digest&&"<none>"!==t.Digest?[`${n}@${t.Digest}`]:[];return{repository:n,tag:r,id:i,createdSince:t.CreatedSince,size:t.Size,reference:s,repoDigests:o}}).filter(e=>Boolean(e.reference))}(e)}function An(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function bn(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 wn=u.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),Nn=u.z.object({type:u.z.enum(["app-session","provider-session","adapter-key"]),id:u.z.string().trim().min(1).max(240),agent:u.z.string().trim().min(1).max(80).optional(),adapter:u.z.string().trim().min(1).max(80).optional(),key:u.z.string().trim().min(1).max(240).optional()}).strict(),zn=u.z.record(u.z.string(),u.z.unknown()).and(u.z.object({id:u.z.string().trim().min(1).max(160),appId:u.z.string().trim().min(1).max(160).optional(),title:u.z.string().trim().max(240).optional(),kind:u.z.string().trim().max(80).optional(),status:wn.default("unknown"),bindings:u.z.array(Nn).max(40).default([]),workspace:u.z.object({cwd:u.z.string().trim().max(4096).optional()}).strict().optional(),createdAt:u.z.string().datetime().optional(),updatedAt:u.z.string().datetime().optional()})),vn=u.z.object({runningCount:u.z.number().int().min(0).default(0),problemCount:u.z.number().int().min(0).default(0),sessions:u.z.array(zn).default([]),updatedAt:u.z.string().datetime()}).strict();u.z.object({streamId:u.z.string().trim().min(1).max(240),revision:u.z.number().int().min(0),lastEventAt:u.z.string().datetime(),snapshot:vn}).strict(),vn.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:u.z.number().int().min(0).optional()});const En=u.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Sn=u.z.object({streamId:u.z.string().trim().min(1).max(240),instanceId:u.z.string().trim().min(1).max(160),nodeId:u.z.string().trim().min(1).max(160).optional(),revision:u.z.number().int().min(0),previousRevision:u.z.number().int().min(0).optional(),traceId:u.z.string().trim().min(1).max(160),generatedAt:u.z.string().datetime(),reason:En}).strict(),_n=u.z.object({meta:Sn,snapshot:vn}).strict(),Tn=u.z.object({meta:Sn,session:zn}).strict(),kn=u.z.object({meta:Sn,sessionId:u.z.string().trim().min(1).max(160),tombstone:zn.optional(),expiresAt:u.z.string().datetime().optional()}).strict();function Cn(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":"system"}u.z.object({streamId:u.z.string().trim().min(1).max(240),instanceId:u.z.string().trim().min(1).max(160),sinceRevision:u.z.number().int().min(0),latestRevision:u.z.number().int().min(0),earliestRetainedRevision:u.z.number().int().min(0),syncRequired:u.z.boolean().default(!1),events:u.z.array(u.z.discriminatedUnion("type",[u.z.object({type:u.z.literal("app-session.snapshot"),payload:_n}).strict(),u.z.object({type:u.z.literal("app-session.patch"),payload:Tn}).strict(),u.z.object({type:u.z.literal("app-session.removed"),payload:kn}).strict()])).default([])}).strict();const xn=u.z.enum(["ai.sessions","app.sessions"]),On=u.z.object({topic:xn,instanceId:u.z.string().trim().min(1).max(160),streamId:u.z.string().trim().min(1).max(240),latestRevision:u.z.number().int().min(0),earliestRetainedRevision:u.z.number().int().min(0)}).strict(),Rn=u.z.object({protocolVersion:u.z.literal(1),streams:u.z.array(On)}).strict();class Dn{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 r=t.setTimeoutFn||setTimeout;return this.timer=r(()=>{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 jn(e,t=6e4){const n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}class Pn{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 r;this.state=e,this.token=t,this.logger=n.logger,this.safetyIntervalMs=(r=n.safetyIntervalMs,Math.min(6e4,Math.max(3e4,r??45e3))),this.createSocket=n.createSocket||((e,t)=>new l(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=Mn(t);n?this.sendForwarded(e,this.createEvent(Xt,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)jn(n.tail).forEach((r,i)=>this.sendForwarded(e,this.createEvent(Dt,{...n.output,sequence:n.output.sequence+i,data:r,...0===i?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(jt,n.finished,{instanceId:t}));return this.syncNow(),()=>{this.outputs.delete(e)}}publish(e,t,n={}){this.rememberImagePullTerminal(e,t);const r=this.createEvent(e,t,n);for(const e of this.outputs)this.sendForwarded(e,r)}rememberImagePullTerminal(e,t){if(e===Dt){const e=Mt.safeParse(t);if(!e.success)return;const n=e.data,r=this.imagePullTerminalByInstance.get(n.instanceId);if(r&&n.generation<r.output.generation)return;const i=r?.output.generation===n.generation,s=n.replay||!i?n.data:`${r.tail}${n.data}`.slice(-262144);return void this.imagePullTerminalByInstance.set(n.instanceId,{output:n,tail:s})}if(e===jt){const e=Lt.safeParse(t);if(!e.success)return;const n=e.data,r=this.imagePullTerminalByInstance.get(n.instanceId);r?.output.generation===n.generation&&(r.finished=n)}}publishInstanceLifecycle(e){this.publish(Xt,function(e){return Zt.parse(Ln(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 r=++this.localSequence;return{v:1,id:`node_evt_${Date.now().toString(36)}_${r.toString(36)}`,seq:r,type:e,topic:Cn(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===l.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=Fn(e);if(!n)continue;t.add(e.id);const r=this.retries.get(e.id);r?.timer.pending&&r.url!==n&&(r.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,r=this.createSocket(t,{headers:n});this.sockets.set(e,r),this.socketUrls.set(e,t),r.on("open",()=>{const n=this.retries.get(e);n?.timer.reset(),this.retries.set(e,{timer:n?.timer||new Dn,url:t}),r.readyState===l.OPEN&&(r.send(JSON.stringify({v:1,type:"subscribe",topics:[N,"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"))}),r.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 r=n,i="string"==typeof r.type?r.type:"";if(!i||"events.connected"===i)return;const s=r.scope&&"object"==typeof r.scope&&!Array.isArray(r.scope)?r.scope:{};return{v:1,id:"string"==typeof r.id?r.id:`evt_${Date.now().toString(36)}`,seq:Number(r.seq)||0,type:i,topic:"string"==typeof r.topic?r.topic:Cn(i),createdAt:"string"==typeof r.createdAt?r.createdAt:(new Date).toISOString(),payload:"payload"in r?r.payload:{},scope:{...s,instanceId:t}}}catch{return}}(t,e);if(!n)return;if("streams.hello"===n.type){const t=Rn.safeParse(n.payload);if(!t.success)return this.logger?.warn?.({instanceId:e,issues:t.error.issues},"session-stream.handshake.invalid"),void r.close(1002,"Incompatible session stream handshake.");const i=JSON.stringify({type:"node-agent.streams.hello",instanceId:e,payload:t.data});for(const e of this.outputs)e.readyState===l.OPEN&&e.send(i);return}this.recordAiSessionEvent(e,n),this.recordAppSessionEvent(e,n);const i=JSON.stringify({type:"node-agent.event.forwarded",event:n});for(const e of this.outputs)e.readyState===l.OPEN&&e.send(i)}),r.on("close",()=>{this.sockets.get(e)===r&&(this.sockets.delete(e),this.socketUrls.delete(e),this.scheduleReconnect(e))}),r.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"),r.close()})}scheduleReconnect(e){const t=this.state.listInstances().find(t=>t.id===e),n=t&&Fn(t);if(!n||!this.outputs.size)return;const r=this.retries.get(e)??{timer:new Dn};if(r.timer.pending)return;r.url=n;const i=r.timer.schedule(()=>{this.sockets.has(e)||this.connect(e,n)});i&&(this.reconnectAttempts+=1,this.logger?.info?.({instanceId:e,url:n,attempt:i.attempt,delay:i.delay,reconnectAttempts:this.reconnectAttempts},"session-stream.connection.reconnect-scheduled")),this.retries.set(e,r)}recordAiSessionEvent(e,t){if(t.topic!==N)return;if("ai-session.message-delta"===t.type)return;const n=$n(t.payload),r=this.lastAiSessionEventByInstance.get(e);r?.streamId===n.streamId&&void 0!==r.revision&&void 0!==n.revision&&n.revision>r.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:r.revision,revision:n.revision},"ai-session.event.forward.gap"),this.lastAiSessionEventByInstance.set(e,{streamId:n.streamId??r?.streamId,revision:n.revision??r?.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=$n(t.payload),r=this.lastAppSessionEventByInstance.get(e);r?.streamId===n.streamId&&void 0!==r.revision&&void 0!==n.revision&&n.revision>r.revision+1&&this.logger?.warn?.({instanceId:e,traceId:n.traceId,streamId:n.streamId,previousRevision:r.revision,revision:n.revision},"app-session.event.forward.gap"),this.lastAppSessionEventByInstance.set(e,{streamId:n.streamId??r?.streamId,revision:n.revision??r?.revision}),this.logger?.info?.({instanceId:e,traceId:n.traceId,eventType:t.type,streamId:n.streamId,revision:n.revision},"app-session.event.forward.message")}}function Mn(e){const t=Zt.safeParse(Ln(e));return t.success?t.data:void 0}function Ln(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 $n(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 Fn(e){const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const Un=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),Vn=JSON.stringify({id:"{{.ID}}",name:"{{.Name}}",cpu:"{{.CPUPerc}}",memory:"{{.MemUsage}}",memoryPercent:"{{.MemPerc}}",network:"{{.NetIO}}",blockIo:"{{.BlockIO}}",pids:"{{.PIDs}}"});class Hn{snapshots=new Map;runCommand;targets;publish;intervalMs;timer;inFlight;pendingTargets=new Map;constructor(e,t,n,r=3e3){this.runCommand=e,this.targets=t,this.publish=n,this.intervalMs=r}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 Un.has(t.status)?(await this.collect([t]),this.snapshots.get(e)):Jn(t.id)}async collect(e){const t=e||this.targets();if(!e){const e=new Set(t.map(e=>e.id));for(const t of this.snapshots.keys())e.has(t)||this.snapshots.delete(t)}for(const e of t)this.pendingTargets.set(e.id,e);this.inFlight||(this.inFlight=this.drain().finally(()=>{this.inFlight=void 0})),await this.inFlight,this.pendingTargets.size&&await this.collect([])}async drain(){for(;this.pendingTargets.size;){const e=[...this.pendingTargets.values()];this.pendingTargets.clear(),await this.collectOnce(e)}}async collectOnce(e){const t=e.filter(e=>Un.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>Un.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(Wn(t.id));for(const t of e.filter(e=>!Un.has(e.status)))this.update(Jn(t.id));if(!t.length)return;const n=t.map(e=>e.runtime.containerId||e.runtime.containerName),r=(new Date).toISOString();try{const e=await this.runCommand("docker",["stats","--no-stream","--format",Vn,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,r)}catch(e){if(1===t.length)return void this.update(Yn(t[0].id,r,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",Vn,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,r)}catch(t){this.update(Yn(e.id,r,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const r=function(e,t=(new Date).toISOString()){const n=new Map;for(const r of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(r)}catch{continue}const i=Gn(e.id),s=Gn(e.name),o=i||s;if(!o)continue;const a=qn(Gn(e.memory)),c=qn(Gn(e.network)),d=qn(Gn(e.blockIo)),l=Ut.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:Bn(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...Bn(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:Kn(e.pids)});i&&n.set(i,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),i=[...r.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(i?{...i,instanceId:t.id}:Yn(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=Ut.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function qn(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]),r=t[2].toLowerCase(),i=r.includes("i"),s="b"===r[0]?"":r[0],o=s?"kmgtpe".indexOf(s)+1:0;return Math.round(n*(i?1024:1e3)**o)}(e||""));return void 0===t?void 0:[t,n]}function Bn(e,t){const n=Number(Gn(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function Kn(e){const t=Number(Gn(e));return Number.isFinite(t)&&t>=0?t:void 0}function Gn(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function Jn(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function Wn(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function Yn(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function Xn(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function Zn(e,r){let i;try{i=t.statSync(e)}catch{return}if(!i.isDirectory())return;const s=n.resolve(e),o=n.basename(s)||s;let a=[];try{a=r>0?t.readdirSync(s,{withFileTypes:!0}):[]}catch{a=[]}const c=r>0?a.filter(e=>e.isDirectory()||e.isSymbolicLink()&&Xn(n.join(s,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=Zn(n.join(s,e.name),r-1);return t?[t]:[]}):[];return{name:o,path:s,children:c}}function Qn(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(Xn)}()).flatMap(t=>{const n=Zn(t,e.depth);return n?[n]:[]})}const er=u.z.object({path:u.z.string().trim().min(1).max(2048),method:u.z.string().trim().min(1).max(20).default("GET"),headers:u.z.record(u.z.string(),u.z.string()).default({}),body:u.z.string().optional(),bodyBase64:u.z.string().optional()}).strict(),tr=u.z.object({id:u.z.string().trim().min(1).max(120).optional(),name:u.z.string().trim().min(1).max(160),path:u.z.string().trim().min(1).max(4096),defaultImageId:u.z.string().trim().min(1).max(120).optional(),labels:u.z.record(u.z.string(),u.z.string()).default({})}).strict(),nr=u.z.object({path:u.z.string().trim().min(1).max(4096).optional(),depth:u.z.coerce.number().int().min(0).max(1).default(0)}).strict(),rr=u.z.object({id:u.z.string().trim().min(1).max(120).optional(),name:u.z.string().trim().min(1).max(160).optional(),runtimeId:u.z.string().trim().min(1).max(120),imageId:u.z.string().trim().min(1).max(120).optional(),projectId:u.z.string().trim().min(1).max(120).optional(),image:xt.optional(),source:ht,sourceSnapshot:u.z.record(u.z.string(),u.z.unknown()).default({}),config:u.z.object({autoImportAgentConfigs:u.z.boolean().optional(),defaultCodexPermissionMode:L.optional()}).strict().optional(),modelSelection:Yt.shape.modelSelection}).strict(),ir=u.z.object({name:u.z.string().trim().min(1).max(160).optional(),config:u.z.object({autoImportAgentConfigs:u.z.boolean().optional(),defaultCodexPermissionMode:L.optional()}).strict().optional(),modelSelection:Yt.shape.modelSelection.optional()}).strict(),sr=u.z.object({id:u.z.string().trim().min(1).max(120).optional(),name:u.z.string().trim().min(1).max(160),type:u.z.enum(["docker","kubernetes","local"]),status:u.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:u.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).optional(),capabilities:u.z.record(u.z.string(),u.z.unknown()).default({}),labels:u.z.record(u.z.string(),u.z.string()).default({})}).strict(),or=sr.omit({id:!0}).partial().strict();function ar(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(h.homedir(),".config","task-handoff","node-agent")}function cr(e=ar()){const t=n.resolve(e);return{dataDir:t,identityPath:n.join(t,"identity.json"),settingsPath:n.join(t,"runtime-settings.json"),localFoldersDir:n.join(t,"local-folders"),nodeRuntimesDir:n.join(t,"node-runtimes"),controlledInstancesDir:n.join(t,"controlled-instances"),nodeModelsDir:n.join(t,"models"),modelAssignmentsDir:n.join(t,"model-assignments"),modelEnvironmentsDir:n.join(t,"model-environments"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}function dr(e){t.mkdirSync(e,{recursive:!0})}function lr(e,t){dr(n.dirname(e)),g.sync(e,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8"})}function ur(e,t){console.warn(JSON.stringify({message:e,...t}))}function mr(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function pr(e,n){const r=n.logger||ur;let i;try{i=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void r("stored JSON could not be read",{filePath:e,...mr(t)})}if(!n.schema)return i;const s=n.sanitize?n.sanitize(i):i,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 r("unknown stored fields were ignored",{filePath:e,issues:o.error.issues}),a.data;r("stored record failed validation and was isolated",{filePath:e,issues:o.error.issues})}function hr(e){return`${e}_${m.randomUUID().replace(/-/g,"").slice(0,20)}`}function gr(){return m.randomBytes(24).toString("base64url")}class fr{directory;options;constructor(e,t={}){this.directory=e,this.options=t}init(){dr(this.directory)}filePath(e){return n.join(this.directory,`${e}.json`)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=pr(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){const n=this.filePath(e);return t.existsSync(n)?pr(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 lr(this.filePath(n.id),n),n}patch(e,t){const n=this.get(e);if(!n)return;const r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:(new Date).toISOString()};return this.put(r)}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}}class Ir{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){dr(n.dirname(this.filePathValue)),t.existsSync(this.filePathValue)||this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?pr(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 lr(this.filePathValue,n),n}}class yr extends Error{code;lockPath;owner;constructor(e,t,n={}){const r=t?.pid?` pid ${t.pid}`:"";super(`${n.label||"Process"} is already running${r}. Lock: ${e}`),this.name="ProcessSingletonError",this.code=n.code||"PROCESS_ALREADY_RUNNING",this.lockPath=e,this.owner=t}}function Ar(e){return n.join(e,"owner.json")}function br(e){return n.join(e,"initializing.json")}function wr(e){return n.join(e,"recovering.json")}function Nr(e){try{const n=JSON.parse(t.readFileSync(Ar(e),"utf8"));if(!Number.isInteger(n.pid)||Number(n.pid)<=0||"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}}function zr(e){if(!Number.isInteger(e)||Number(e)<=0)return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function vr(e,r){const i=n.join(e,`.owner-${r.token}.tmp`);t.writeFileSync(i,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384,flag:"wx"});const s=Er(e);if(s?.token!==r.token)throw Sr(i),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(i,Ar(e)),Sr(br(e))}function Er(e){try{return JSON.parse(t.readFileSync(br(e),"utf8"))}catch{return}}function Sr(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function _r(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function Tr(e){try{const n=Er(e),r=Date.parse(n?.startedAt||"");return Number.isFinite(r)?Math.max(0,Date.now()-r):Math.max(0,Date.now()-t.statSync(e).mtimeMs)}catch{return 0}}function kr(e,r){try{return t.writeFileSync(wr(e),`${JSON.stringify({token:r,pid:process.pid,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),!0}catch(i){if("EEXIST"===i.code)return!!function(e){const r=wr(e),i=Cr(r),s=Date.parse(i?.startedAt||"");if(zr(i?.pid)||Number.isFinite(s)&&Date.now()-s<2e3)return!1;const o=n.join(e,`.recovering-${m.randomUUID()}.stale`);try{t.renameSync(r,o)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=Cr(o);if(a?.token===i?.token)return Sr(o),!0;try{t.linkSync(o,r)}catch(e){if("EEXIST"!==e.code)throw e}finally{Sr(o)}return!1}(e)&&kr(e,r);if("ENOENT"===i.code)return!1;throw i}}function Cr(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function xr(e,t){return Cr(wr(e))?.token===t}function Or(e,t=process.platform){const r=n.resolve(e),i=m.createHash("sha256").update(r).digest("hex").slice(0,16);return"win32"===t?`\\\\.\\pipe\\task-handoff-node-agent-${i}`:n.join("/tmp",`task-handoff-node-agent-${process.getuid?.()??"user"}`,`${i}.sock`)}const Rr="TASK_HANDOFF_NODE_AGENT_V1";function Dr(e=""){return m.createHash("sha256").update(e).digest("hex")}function jr(e,t){return m.createHmac("sha256",e).update(function(e){return[Rr,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function Pr(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||m.randomBytes(18).toString("base64url"),r=Dr(e.body||""),i=jr(e.secret,{keyId:e.keyId,method:e.method,pathWithQuery:e.pathWithQuery,timestamp:t,nonce:n,bodySha256:r});return{"x-taskhandoff-node-id":e.nodeId,"x-taskhandoff-key-id":e.keyId,"x-taskhandoff-timestamp":t,"x-taskhandoff-nonce":n,"x-taskhandoff-body-sha256":r,"x-taskhandoff-signature":i}}const Mr=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function Lr(e){return"string"==typeof e&&Mr.has(e.toUpperCase())?e.toUpperCase():"GET"}function $r(){return(new Date).toISOString()}function Fr(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function Ur(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:$r(),r=t.target&&"object"==typeof t.target&&!Array.isArray(t.target)?t.target:void 0,i="controlled-instance"===r?.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=i?"failed":o.has(a)?a:s[a]||"failed",d="string"==typeof t.toVersion&&t.toVersion?t.toVersion:"unknown",l=it.strip().safeParse(t.impact).success?it.strip().parse(t.impact):{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},u=i?{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}:nt.strip().safeParse(t.error).success?nt.strip().parse(t.error):t.error&&"object"==typeof t.error?{code:"NODE_UPDATE_FAILED",message:"string"==typeof t.error.message?t.error.message:"Stored update job contained an unknown error.",retryable:!1}:void 0:{code:"NODE_UPDATE_FAILED",message:`Stored update job used an unknown status: ${a}.`,retryable:!1},{target:m,error:p,...h}=t,g={phase:"succeeded"===c?"succeeded":"failed"===c?"failed":c||"queued",desiredVersion:d,expectedInstanceIds:[],expectedInstanceCount:0,matchedInstanceCount:0,pendingInstanceCount:0,failedInstanceCount:i||"failed"===c?1:0,deferredInstanceCount:0},f=st.strip().safeParse(t.rollout);return{...h,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:g,...u?{error:u}:{},...i?{completedAt:t.completedAt||n}:{}}}class Vr{records;constructor(e){this.records=new fr(e.updatesDir,{schema:ct,sanitize:Ur})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=$r();return this.records.put(ct.parse({id:hr("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(ct.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:$r()}))}reconcileRollouts(e,t){const n=new Map(e.map(e=>[e.id,e]));for(const e of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status))){const 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 i=r.rollout.expectedInstanceIds,s=i.map(e=>n.get(e)),o=s.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===r.toVersion).length,a=s.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,c=s.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,d=Math.max(0,i.length-o-c-a),l=c>0?"degraded":0===d?"succeeded":"converging-instances";this.patch(r.id,{status:l,rollout:{...r.rollout,phase:l,nodeVersion:t,expectedInstanceCount:i.length,matchedInstanceCount:o,pendingInstanceCount:d,failedInstanceCount:c,deferredInstanceCount:r.impact.stoppedInstanceCount+a},..."succeeded"===l||"degraded"===l?{completedAt:$r()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:$r(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:$r()})}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:$r()})}})()}}const Hr="runtime-manifest.json";class qr 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 Br(e,t=""){const r=[],i=await I.readdir(n.join(e,t),{withFileTypes:!0});for(const s of i){const i=t?n.posix.join(t,s.name):s.name;if(!t&&i===Hr)continue;const o=n.join(e,...i.split("/"));if(s.isDirectory()){r.push(...await Br(e,i));continue}if(s.isSymbolicLink()){const t=await I.readlink(o);if(n.isAbsolute(t))throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is absolute: ${i}`);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 qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${i}`);if(!await I.lstat(s).catch(()=>{}))throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink is broken: ${i}`);r.push({absolutePath:o,relativePath:i,kind:"symlink",target:t,size:Buffer.byteLength(t)});continue}if(!s.isFile())throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${i}`);const a=await I.lstat(o);r.push({absolutePath:o,relativePath:i,kind:"file",size:a.size})}return r}async function Kr(e){const n=(await Br(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),r=m.createHash("sha256");for(const e of n){if(r.update("file"===e.kind?"F":"L","ascii"),r.update(Buffer.from(e.relativePath,"utf8")),r.update(Buffer.from([0])),r.update(Buffer.from(String(e.size),"ascii")),r.update(Buffer.from([0])),"file"===e.kind)for await(const n of t.createReadStream(e.absolutePath))r.update(n);else r.update(Buffer.from(e.target,"utf8"));r.update(Buffer.from([0]))}return r.digest("hex")}function Gr(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function Jr(e,t){return`${Gr(e)}-${e.sha256}-${t}`}async function Wr(e){let t;try{t=JSON.parse(await I.readFile(n.join(e,Hr),"utf8"))}catch(e){throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const r=tt.safeParse(t);if(!r.success)throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact manifest is invalid: ${r.error.message}`);return r.data}async function Yr(e,t,r){const i=await Wr(e);if(function(e,t){for(const n of["packageName","version","platform","arch","formatVersion","launcherAbi","entrypoint","sha256"])if(e[n]!==t[n])throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact ${"sha256"===n?"SHA-256":n} mismatch: expected ${t[n]}, got ${e[n]}.`)}(i,t),1!==i.formatVersion)throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${i.formatVersion}.`);if(r?.platform&&"universal"!==i.platform&&i.platform!==r.platform)throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact platform ${i.platform} does not match ${r.platform}.`);if(r?.arch&&"universal"!==i.arch&&i.arch!==r.arch)throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime artifact architecture ${i.arch} does not match ${r.arch}.`);if(void 0!==r?.launcherAbi&&i.launcherAbi>r.launcherAbi)throw new qr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${i.launcherAbi}, but the base runtime provides ${r.launcherAbi}.`);const s=function(e,t){if(!e||e.includes("\\")||n.posix.isAbsolute(e))throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} must be a non-empty POSIX relative path.`);const r=n.posix.normalize(e);if("."===r||".."===r||r.startsWith("../"))throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return r}(i.entrypoint,"Runtime entrypoint"),o=await I.lstat(n.join(e,...s.split("/"))).catch(()=>{});if(!o?.isFile())throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${s}`);const a=await Kr(e);if(a!==i.sha256)throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload SHA-256 mismatch: expected ${i.sha256}, got ${a}.`);return i}async function Xr(e,t){await I.mkdir(t,{recursive:!0});try{await A.extract({file:e,cwd:t,strict:!0,preservePaths:!1,filter:(e,t)=>{const r=n.posix.normalize(e.replace(/^\.\//,""));if(!r||".."===r||r.startsWith("../")||n.posix.isAbsolute(r))throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive entry escapes the artifact root: ${e}`);const i=t.type;if("File"!==i&&"OldFile"!==i&&"Directory"!==i&&"SymbolicLink"!==i)throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${i??"unknown"}: ${e}`);return!0}})}catch(e){throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Could not extract runtime artifact safely.",{cause:e})}}async function Zr(e){const n=m.createHash("sha256");for await(const r of t.createReadStream(e))n.update(r);return n.digest("hex")}class Qr{#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 qr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const r=Jr(n,t.archiveSha256),i=this.#n.get(r);if(i)return i;const s=this.#r(n,t).finally(()=>this.#n.delete(r));return this.#n.set(r,s),s}async#r(e,r){if(!/^[a-f0-9]{64}$/.test(r.archiveSha256))throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const i=Jr(e,r.archiveSha256),s=n.join(this.#e,"archives"),o=n.join(s,`${i}.tar.gz`);if(await I.mkdir(s,{recursive:!0}),await this.#i(o,e,r.archiveSha256))return{identity:e,archivePath:o,cacheHit:!0};await I.rm(o,{force:!0});const a=n.join(s,`.${i}.${m.randomUUID()}.part`);try{const n=await I.open(a,"wx");if(r.archivePath)await y.pipeline(t.createReadStream(r.archivePath),n.createWriteStream());else{const e=await this.#t(r.archiveUrl);if(!e.ok||!e.body)throw await n.close(),new qr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await y.pipeline(e.body,n.createWriteStream())}if(await Zr(a)!==r.archiveSha256)throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#s(a,e),await I.rename(a,o),{identity:e,archivePath:o,cacheHit:!1}}catch(e){if(e instanceof qr)throw e;throw new qr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await I.rm(a,{force:!0})}}async#i(e,t,n){try{return await Zr(e)===n&&(await this.#s(e,t),!0)}catch{return!1}}async#s(e,t){const r=n.join(this.#e,"validation",`${Gr(t)}-${m.randomUUID()}`);try{await Xr(e,r),await Yr(r,t,{platform:t.platform,arch:t.arch})}finally{await I.rm(r,{recursive:!0,force:!0})}}}async function ei(e,t,r=process.platform){const i=n.join(e,`.current-${m.randomUUID()}`),s=n.join(e,"current");if(await I.symlink(n.posix.join("releases",t),i,"win32"===r?"junction":"dir"),"win32"!==r)return void await I.rename(i,s);const o=n.join(e,`.previous-current-${m.randomUUID()}`);let a=!1;try{await I.rename(s,o),a=!0}catch(e){if("ENOENT"!==e.code)throw await I.rm(i,{recursive:!0,force:!0}),e}try{await I.rename(i,s)}catch(e){throw a&&await I.rename(o,s).catch(()=>{}),e}finally{await I.rm(i,{recursive:!0,force:!0})}a&&await I.rm(o,{recursive:!0,force:!0})}async function ti(e,t,r,i=fetch){if("linux"!==t||!["x64","arm64"].includes(r))throw new qr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${r}.`);const s=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,r=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[i,s]=await Promise.all([I.readFile(n.join(r,`${t}.manifest.json`),"utf8"),I.readFile(n.join(r,`${t}.tar.gz.sha256`),"utf8")]),o=tt.safeParse(JSON.parse(i));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new qr("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 qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Bundled controlled-instance ${e} has an invalid archive checksum.`);return{identity:o.data,source:{archivePath:n.join(r,`${t}.tar.gz`),archiveSha256:a}}}catch(t){if("ENOENT"===t.code)return;if(t instanceof qr)throw t;throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(s)return s;const o=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${o}.manifest.json`,d=`${a}/${o}.tar.gz`,l=`${a}/${o}.tar.gz.sha256`,[u,m]=await Promise.all([i(c),i(l)]).catch(t=>{throw new qr("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new qr("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 qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const h=tt.safeParse(p);if(!h.success)throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is invalid: ${h.error.message}`);if(h.data.version!==e||"linux"!==h.data.platform||"universal"!==h.data.arch)throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${h.data.version}-${h.data.platform}-${h.data.arch}.`);const g=(await m.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!g||!/^[a-f0-9]{64}$/.test(g))throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:h.data,source:{archiveUrl:d,archiveSha256:g}}}class ni{store;desiredVersion;hooks;inFlight=new Map;requests=new Map;cancelled=new Set;now;delay;drainTimeoutMs;verificationTimeoutMs;pollIntervalMs;maxAttempts;retryBaseDelayMs;retryMaxDelayMs;constructor(e,t,n,r={}){this.store=e,this.desiredVersion=t,this.hooks=n,this.now=r.now||(()=>new Date),this.delay=r.delay||(e=>new Promise(t=>setTimeout(t,e))),this.drainTimeoutMs=r.drainTimeoutMs??3e5,this.verificationTimeoutMs=r.verificationTimeoutMs??6e4,this.pollIntervalMs=r.pollIntervalMs??250,this.maxAttempts=function(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("maxAttempts must be a positive integer.");return e}(r.maxAttempts??3),this.retryBaseDelayMs=li(r.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=li(r.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 r=this.inFlight.get(e);if(r)return r;const i=Promise.resolve().then(()=>this.reconcile(e,n)).finally(()=>{this.inFlight.delete(e),this.requests.delete(e)});return this.inFlight.set(e,i),i}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 r=this.desiredVersion();if(this.cancelled.has(e)&&!t.resumeCancelled)return this.storePhase(n,"pending");const i=ri(n),s=i===r&&(await(this.hooks.isInstalled?.(n,r))??!0);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(i===r&&s)return this.storeState(n,{desiredVersion:r,actualVersion:i,phase:"matched",attempt:n.runtimeVersion?.attempt||0,matchedAt:this.timestamp()},!si(n)&&"failed"!==n.health);if(n.runtimeVersion?.desiredVersion===r&&(n.runtimeVersion?.attempt||0)>=this.maxAttempts)return"failed"===n.runtimeVersion?.phase&&n.runtimeVersion.error?n:this.storePermanentFailure(n,r,di(r,i,this.maxAttempts,n.runtimeVersion?.error));if(n=this.storeState(n,function(e,t,n,r=!1){const i=e.runtimeVersion;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:i?.desiredVersion===t&&"matched"!==i.phase?i.attempt:0,error:n!==t||r?oi(t,n):ai("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,r,i,s),!1),si(n)&&!t.startRequested)return n;for(;(n.runtimeVersion?.attempt||0)<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let i,s=!1;try{if(ii(n)){n=this.storePhase(n,"draining");const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!ii(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,r),s=!0,this.cancelled.has(e)||si(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 i=await this.waitUntil(e,this.verificationTimeoutMs,e=>ri(e)===r);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!i)throw ai("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${r} after restart.`,r,ri(this.requireInstance(e)),!0);const o=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(o,r))throw ai("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${r}, but its active runtime release is missing.`,r,ri(o),!0);return this.storeState(o,{desiredVersion:r,actualVersion:r,phase:"matched",attempt:o.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!si(o)&&"failed"!==o.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(i=ci(t,r,ri(this.store.get(e))),s&&this.hooks.rollback)try{await this.hooks.rollback(this.requireInstance(e))}catch(e){i.message=`${i.message} Rollback failed: ${e instanceof Error?e.message:String(e)}`,i.retryable=!1}}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!i.retryable||o>=this.maxAttempts)return this.storePermanentFailure(n,r,o>=this.maxAttempts&&i.retryable?di(r,ri(n),this.maxAttempts,i):i);n=this.storeState(n,{desiredVersion:r,...ri(n)?{actualVersion:ri(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:i},!1),await this.delay(this.retryDelayMs(o))}return this.storePermanentFailure(n,r,di(r,ri(n),this.maxAttempts,n.runtimeVersion?.error))}storePermanentFailure(e,t,n){const r=ri(e);return this.storeState(e,{desiredVersion:t,...r?{actualVersion:r}:{},phase:"failed",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:{...n,retryable:!1}},!1)}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}storePhase(e,t,n=!1){const r=this.desiredVersion(),i=ri(e);return this.storeState(e,{desiredVersion:r,...i?{actualVersion:i}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),..."pending"===t?{error:oi(r,i)}:{}},!1)}storeState(e,t,n){const r=this.store.get(e.id)||e;return this.store.put(Yt.parse({...r,runtimeVersion:t,ready:n,...n?{}:{health:"failed"===r.health?"failed":"degraded"},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const r=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()>=r)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,r-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 ri(e){return e?.build?.packageVersion||e?.instanceVersion}function ii(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function si(e){return["created","stopped","failed"].includes(e.status)}function oi(e,t){return ai("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function ai(e,t,n,r,i){return{code:e,message:t,expectedVersion:n,...r?{actualVersion:r}:{},retryable:i}}function ci(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const r=e;return ai(r.code,r.message,t,n,r.retryable??!0)}return ai("INSTANCE_RUNTIME_INSTALL_FAILED",e instanceof Error?e.message:String(e),t,n,!0)}function di(e,t,n,r){const i=r?.message?` Last error: ${r.message}`:"";return ai(r?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence exhausted ${n} attempts.${i}`,e,t,!1)}function li(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}const ui=u.z.record(u.z.string(),u.z.string()),mi=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 pi{directory;constructor(e){this.directory=e}get(e){try{return ui.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 r=ui.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const i=this.filePath(e);return g.sync(i,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),r}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class hi{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=At.parse(e);this.init();const r=this.filePath(n.id);return g.sync(r,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const r=JSON.parse(t.readFileSync(e,"utf8")),i=n.basename(e,".json"),s=At.safeParse(r);if(s.success&&s.data.id===i&&Ct(s.data)===s.data.id)return s.data;const o=At.strip().safeParse(r);return o.success&&o.data.id===i&&Ct(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 gi{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 r=JSON.parse(t.readFileSync(n,"utf8")),i=Nt.safeParse(r);if(i.success)return i.data;const s=Nt.strip().safeParse(r);if(s.success)return console.warn(JSON.stringify({message:"unknown stored model assignment fields were ignored",instanceId:e,filePath:n})),s.data;throw i.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=Nt.parse(e);this.init();const r=this.filePath(n.instanceId);return g.sync(r,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class fi{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,r,i=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=r,this.nowMs=i}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,r]of Object.entries(e)){const e=Array.isArray(r)?r.join(","):"string"==typeof r?r:void 0===r?"":String(r);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId);if(!n.length)return!1;if(t.nodeId!==this.nodeId)throw Object.assign(new Error("Invalid node agent HMAC node id."),{statusCode:401,code:"NODE_AGENT_HMAC_NODE_MISMATCH"});if(!t.keyId)throw Object.assign(new Error("Node agent HMAC key id is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_MISSING"});const r=n.filter(e=>t.keyId===e.keyId);if(!r.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const i=Date.parse(t.timestamp);if(!Number.isFinite(i)||Math.abs(this.nowMs()-i)>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 o=Dr(null==(a=e.body)?"":"string"==typeof a||Buffer.isBuffer(a)?a:JSON.stringify(a));var a;if(t.bodySha256!==o)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!r.some(n=>function(e,t){const n=Buffer.from(e,"hex"),r=Buffer.from(t,"hex");return n.length===r.length&&m.timingSafeEqual(n,r)}(t.signature,jr(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:o}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(s,i+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const Ii=u.z.string().trim().min(1).max(160),yi=u.z.string().datetime(),Ai=u.z.string().min(1).max(4096),bi=u.z.string().trim().url().max(2048),wi=u.z.object({tokenHash:u.z.string().trim().min(1).max(256),expiresAt:yi,createdAt:yi,controlPlaneName:u.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:bi.optional()}).strip(),Ni=u.z.object({id:Ii,keyId:Ii,name:u.z.string().trim().min(1).max(160).optional(),url:bi.optional(),secret:Ai,pairedAt:yi,updatedAt:yi,active:u.z.boolean().default(!0)}).strip(),zi=u.z.object({controlPlaneName:u.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:u.z.string().trim().max(2048).optional(),expiresInMs:u.z.number().int().positive().max(36e5).optional()}).strict(),vi=u.z.object({joinToken:u.z.string().trim().min(1).max(4096),controlPlaneId:u.z.string().trim().min(1).max(160).optional(),controlPlaneName:u.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:u.z.string().trim().max(2048).optional()}).strict(),Ei=u.z.object({controlPlaneUrl:u.z.string().trim().url().max(2048),joinToken:u.z.string().trim().min(1).max(4096),controlPlaneName:u.z.string().trim().min(1).max(160).optional(),activate:u.z.boolean().optional()}).strict();function Si(){return(new Date).toISOString()}const _i=new Set(["nodeId","createdAt","updatedAt","pairingInvites","remoteControlPlanes"]),Ti=new Set(["tokenHash","expiresAt","createdAt","controlPlaneName","controlPlaneUrl"]),ki=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function Ci(e,t){console.warn(JSON.stringify({message:e,...t}))}function xi(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function Oi(e,t){return Object.keys(e).filter(e=>!t.has(e))}function Ri(e,t,n){const r=yi.safeParse(e);return r.success?r.data:(n("invalid node agent identity timestamp was replaced",{field:t}),Si())}function Di(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw xi("Node agent identity must be a JSON object.");const n=e,r=Ii.safeParse(n.nodeId);if(!r.success)throw xi("Node agent identity has an invalid nodeId.",r.error);const i=r.data,s=Oi(n,_i);return s.length&&t("unknown node agent identity fields were ignored",{fields:s}),{nodeId:i,createdAt:Ri(n.createdAt,"createdAt",t),updatedAt:Ri(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=Oi(e,Ti);n.length&&t("unknown node agent pairing invite fields were ignored",{fields:n});const r=wi.safeParse(e);return r.success?[r.data]:(t("invalid node agent pairing invite was ignored",{issues:r.error.issues}),[])}):[],remoteControlPlanes:Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t("invalid node agent remote control-plane was ignored",{}),[];const n=Oi(e,ki);n.length&&t("unknown node agent remote control-plane fields were ignored",{fields:n});const r=Ni.safeParse(e);return r.success?[r.data]:(t("invalid node agent remote control-plane was ignored",{issues:r.error.issues}),[])}):[]}}class ji{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||Ci}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 xi(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return Di(n,this.logger)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const r=Di({...e,updatedAt:Si()},this.logger);g.sync(this.paths.identityPath,`${JSON.stringify(r,null,2)}\n`,{encoding:"utf8",mode:384})}}function Pi(){return(new Date).toISOString()}class Mi{store;constructor(e){this.store=new ji(e)}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=hr("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=Pi(),r=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),i=gr(),s={tokenHash:Dr(i),createdAt:n,expiresAt:r,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{},...e.controlPlaneUrl?{controlPlaneUrl:e.controlPlaneUrl}:{}};return this.store.write({...t,pairingInvites:[...t.pairingInvites||[],s]}),{...s,token:i}}completePairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=Dr(e.joinToken),r=(t.pairingInvites||[]).find(e=>e.tokenHash===n);if(!r){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 i=Pi(),s={id:e.controlPlaneId||hr("cp"),keyId:hr("key"),...e.controlPlaneName||r.controlPlaneName?{name:e.controlPlaneName||r.controlPlaneName}:{},...e.controlPlaneUrl||r.controlPlaneUrl?{url:e.controlPlaneUrl||r.controlPlaneUrl}:{},secret:gr(),pairedAt:i,updatedAt:i,active:!0};return this.store.write({...t,pairingInvites:(t.pairingInvites||[]).filter(e=>e.tokenHash!==n),remoteControlPlanes:[...(t.remoteControlPlanes||[]).filter(e=>e.id!==s.id),s]}),s}upsertRemoteControlPlane(e){const t=this.store.read()||this.newIdentity(),n=e.url?.replace(/\/$/,"");return this.store.write({...t,remoteControlPlanes:[...(t.remoteControlPlanes||[]).filter(t=>t.id!==e.id&&(!n||t.url?.replace(/\/$/,"")!==n)),e]}),e}createRemoteControlPlane(e){const t=Pi();return{id:hr("cp"),keyId:hr("key"),...e.name?{name:e.name}:{},url:e.url,secret:gr(),pairedAt:t,updatedAt:t,active:!1!==e.active}}configuredRemoteControlPlanes(){return this.store.read()?.remoteControlPlanes||[]}listRemoteControlPlanes(e=""){return(this.store.read()?.remoteControlPlanes||[]).map(({secret:t,...n})=>({...n,current:Boolean(e&&n.keyId===e)})).sort((e,t)=>Number(t.current)-Number(e.current)||t.updatedAt.localeCompare(e.updatedAt))}deleteRemoteControlPlane(e,t=""){if(t&&e===t){const e=new Error("Cannot delete the key currently used by this control-plane connection.");throw Object.assign(e,{statusCode:409,code:"NODE_AGENT_REMOTE_KEY_IN_USE"}),e}const n=this.store.read();if(!n)return!1;const r=(n.remoteControlPlanes||[]).filter(t=>t.keyId!==e);return r.length!==(n.remoteControlPlanes||[]).length&&(this.store.write({...n,remoteControlPlanes:r}),!0)}remoteSecrets(e,t){return[...(this.store.read()?.remoteControlPlanes||[]).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const r=this.store.read()?.remoteControlPlanes||[];if(!r.length)return;if(e){const t=e.replace(/\/$/,""),n=r.find(e=>e.url?.replace(/\/$/,"")===t);if(n)return{keyId:n.keyId,secret:n.secret}}const i=[...r].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return i?{keyId:i.keyId,secret:i.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:Pi(),updatedAt:Pi(),pairingInvites:[],remoteControlPlanes:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:Pi()},nodeId:e,updatedAt:Pi(),pairingInvites:t?.pairingInvites||[],remoteControlPlanes:t?.remoteControlPlanes||[]})}prunePairingInvites(e){const t=Date.now();return{...e,pairingInvites:(e.pairingInvites||[]).filter(e=>Date.parse(e.expiresAt)>t)}}}const Li=new Set(["content-encoding","content-length","transfer-encoding"]),$i=["codex","claude"],Fi=5e3,Ui="runtime_local_host",Vi="task-handoff.node-agent.builtin",Hi=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function qi(e){return Hi.has(e)?e:"unknown"}function Bi(e){const t={...e};return delete t[Vi],t}const Ki=u.z.object({version:u.z.literal(1),externalListener:Vt}).strict(),Gi=u.z.object({}).strict().default({}),Ji=dt.strict();function Wi(e){const t=process.env[e]?.trim();return t||void 0}function Yi(){try{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(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,r=[n.resolve(e,"..","package.json"),n.resolve(e,"..","..","package.json")].find(e=>t.existsSync(e));return r&&JSON.parse(t.readFileSync(r,"utf8")).version||"unknown"}catch{return"unknown"}}function Xi(e){const t=Yi();return e===t?{desiredVersion:t,actualVersion:e,phase:"matched",attempt:0,matchedAt:os()}:{desiredVersion:t,...e?{actualVersion:e}:{},phase:"pending",attempt:0,error:{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${t}, received ${e||"an unknown version"}.`,expectedVersion:t,...e?{actualVersion:e}:{},retryable:!0}}}function Zi(e,t){const n=Yi(),r=e.runtimeVersion;return r&&r.desiredVersion===n?rt.parse({...r,desiredVersion:n,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase&&t!==n?{error:{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${n}, received ${t||"an unknown version"}.`,expectedVersion:n,...t?{actualVersion:t}:{},retryable:!0}}:"pending"===r.phase?{error:void 0}:{}}):Xi(t)}function Qi(e){return Object.fromEntries([...e.entries()].filter(([e])=>!Li.has(e.toLowerCase())))}function es(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}const ts=67108864;function ns(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function rs(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function is(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 ss(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function os(){return(new Date).toISOString()}function as(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function cs(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:{},r=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),i=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(r.length||i.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...r,...i.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}function ds(e){return"local-folder"===e.type?gt.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):gt.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function ls(e){const t=ht.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 It.parse({id:n,name:"string"==typeof e.sourceSnapshot.name?e.sourceSnapshot.name:e.name,source:t,defaultImageId:e.imageId,defaultNodeId:e.nodeId,defaultRuntimeId:e.runtimeId,workspacePolicy:ds(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}async function us(e,t){if(!t.target.web)return"unknown";const n=new AbortController,r=setTimeout(()=>n.abort(),2e3);try{return(await e(`${gs(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(r)}}async function ms(e,t,n,r){const i=new AbortController,s=setTimeout(()=>i.abort(),r);try{return await e(t,{...n,signal:i.signal})}finally{clearTimeout(s)}}async function ps(e,t,n,r){if(!t.config.autoImportAgentConfigs)return void r.diagnostic({instanceId:t.id,action:n},"node instance config auto-import skipped");if("reachable"!==t.targetStatus)return;const i=gs(t),s=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||Fi);for(const o of $i)try{const a=await ms(e,`${i}/api/config-sync/import/${encodeURIComponent(o)}`,{method:"POST"},Number.isFinite(s)&&s>0?s:Fi);if(!a.ok){r.warn({instanceId:t.id,action:n,preset:o,statusCode:a.status},"node instance config auto-import failed");continue}r.diagnostic({instanceId:t.id,action:n,preset:o},"node instance config auto-import completed")}catch(e){r.warn({instanceId:t.id,action:n,preset:o,error:e instanceof Error?e.message:String(e)},"node instance config auto-import failed")}}async function hs(e,t,n){const r=t.requireInstance(n);if("reachable"!==r.targetStatus||!r.target.web)return!1;const i=await ms(e,`${gs(r)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${r.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},Fi);if(!i.ok)throw Object.assign(new Error(`Instance ${n} rejected its managed model environment with HTTP ${i.status}.`),{statusCode:502,code:"INSTANCE_MODEL_ENVIRONMENT_APPLY_FAILED"});return!0}function gs(e){const t=e.target.web;if(!t){const t=new Error(`Instance ${e.id} does not have a web endpoint.`);throw Object.assign(t,{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_MISSING"}),t}if("direct-port"!==e.target.strategy)return t.replace(/\/$/,"");try{const e=new URL(t);return e.port?(e.hostname=process.env.TASK_HANDOFF_NODE_AGENT_PROXY_HOST||"127.0.0.1",e.toString().replace(/\/$/,"")):t.replace(/\/$/,"")}catch{return t.replace(/\/$/,"")}}function fs(e,t){const n=new Error(t);throw Object.assign(n,{statusCode:403,code:e}),n}function Is(e,t){e!==be&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:be,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function ys(e={}){return{requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none",...e}}function As(e){return new Promise(t=>{const n=i.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e},()=>{n.close(()=>t(!0))})})}function bs(e,t=3e3){return null!==e.exitCode||null!==e.signalCode?Promise.resolve():new Promise(n=>{const r=setTimeout(()=>{null===e.exitCode&&null===e.signalCode&&e.kill("SIGKILL"),n()},t);r.unref(),e.once("exit",()=>{clearTimeout(r),n()})})}async function ws(e,t){const n=t.get(e.id);if(n&&!n.killed)return n.kill("SIGTERM"),t.delete(e.id),void await bs(n);if(e.runtime.pid){try{process.kill(e.runtime.pid,"SIGTERM")}catch{return}const t=Date.now()+3e3;for(;Date.now()<t;){try{process.kill(e.runtime.pid,0)}catch{return}await new Promise(e=>setTimeout(e,50))}try{process.kill(e.runtime.pid,"SIGKILL")}catch{}}}const Ns=new Set(["provisioning","starting","registering","registered","running"]);async function zs(e,t){try{const n=await e(t,["--version"]);return{available:!0,command:t,version:(n.stdout||n.stderr).split(/\r?\n/)[0]?.trim()||void 0}}catch{return{available:!1}}}function vs(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}class Es{executor;platform;arch;runCommand;constructor(e,t,n,r){this.executor=e,this.runCommand=t,this.platform=n,this.arch=r}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.bootstrapLegacyLauncher(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&&vs(await this.executor.inspectRuntimeVersion(n),t)}async rollbackRuntime(e,t){const n=e.instance.runtime.containerName;n&&await this.executor.rollbackRuntime(n)}start(e){return this.executor.start(e)}stop(e){return this.executor.stop(e)}restart(e){return this.executor.restart(e,e.instance.runtime.containerId)}delete(e){return this.executor.delete(e)}async check(e){try{const t=(await this.runCommand("docker",["version","--format","{{.Server.Version}}"],{timeoutMs:5e3})).stdout.trim();return{status:"online",capabilities:{...e.capabilities,daemon:{status:"online",hostPlatform:qi(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:qi(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class Ss{runCommand;paths;nodeAgentUrl;processByInstanceId=new Map;platform;arch;commandOverride;constructor(e,t,n,r,i,s){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.platform=r,this.arch=i,this.commandOverride=s}async artifactTarget(){return{platform:this.platform,arch:this.arch,launcherAbi:1}}usesManagedArtifact(){return!this.commandOverride}runtimeRoot(e){return n.join(this.paths.dataDir,"local-instances",e,"runtime")}async installRuntime(e,t){await async function(e){const t=tt.parse(e.identity);if(t.launcherAbi>e.launcherAbi)throw new qr("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Runtime requires launcher ABI ${t.launcherAbi}, but the base runtime provides ${e.launcherAbi}.`);const r=Gr(t),i=n.join(e.runtimeRoot,"releases"),s=n.join(e.runtimeRoot,"staging"),o=n.join(e.runtimeRoot,"quarantine"),a=function(e){if(!/^[0-9A-Za-z._-]+$/.test(e.version)||!/^[a-f0-9]{64}$/.test(e.sha256))throw new qr("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime release identity is invalid.");return`${e.version}-${e.sha256}`}(t),c=n.join(i,a);await Promise.all([I.mkdir(i,{recursive:!0}),I.mkdir(s,{recursive:!0}),I.mkdir(o,{recursive:!0})]),await async function(e){await I.rm(n.join(e,"staging"),{recursive:!0,force:!0}),await I.mkdir(n.join(e,"staging"),{recursive:!0})}(e.runtimeRoot);const d=await async function(e){try{const t=(await I.readlink(n.join(e,"current"))).replaceAll("\\","/").match(/(?:^|\/)releases\/([^/]+)$/);return t?.[1]}catch{return}}(e.runtimeRoot),l=d?await Wr(n.join(i,d)).then(e=>e.version).catch(()=>{}):void 0;let u=!1;try{await Yr(c,t,{launcherAbi:e.launcherAbi,platform:e.platform??t.platform,arch:e.arch??t.arch}),u=!0}catch(i){await I.lstat(c).catch(()=>{})&&await I.rename(c,n.join(o,`${r}-${m.randomUUID()}`));const a=n.join(s,`${r}-${m.randomUUID()}`);try{if(await Xr(e.archivePath,a),await Yr(a,t,{launcherAbi:e.launcherAbi,platform:e.platform??t.platform,arch:e.arch??t.arch}),"after-extract"===e.faultInjection)throw new Error("Injected failure after extract.");if(await I.rename(a,c),"after-release"===e.faultInjection)throw new Error("Injected failure after release install.")}catch(e){if(await I.rm(a,{recursive:!0,force:!0}),e instanceof qr)throw e;throw new qr("INSTANCE_RUNTIME_INSTALL_FAILED","Could not install controlled instance runtime.",{cause:e,retryable:!0})}}if(d!==a&&(await ei(e.runtimeRoot,a),d&&await I.writeFile(n.join(e.runtimeRoot,"previous-release"),`${d}\n`,"utf8")),"after-switch"===e.faultInjection)throw new qr("INSTANCE_RUNTIME_INSTALL_FAILED","Injected failure after active release switch.",{retryable:!0});return{releasePath:c,previousVersion:l,previousRelease:d,reused:u}}({archivePath:t.archivePath,identity:t.identity,runtimeRoot:this.runtimeRoot(e.instance.id),launcherAbi:1,platform:this.platform,arch:this.arch})}async inspectRuntime(e,r){try{return vs(JSON.parse(t.readFileSync(n.join(this.runtimeRoot(e.instance.id),"current","runtime-manifest.json"),"utf8")),r)}catch{return!1}}async rollbackRuntime(e,t){await async function(e){const t=(await I.readFile(n.join(e,"previous-release"),"utf8")).trim();if(!t)throw new qr("INSTANCE_RUNTIME_INSTALL_FAILED","No previous verified runtime release is available.");const r=n.join(e,"releases",t),i=await Wr(r);return await Yr(r,i),await ei(e,t),i.version}(this.runtimeRoot(e.instance.id)),await this.restart(e)}async start(e){const r=function(e){if("local-folder"!==e.source.type){const e=new Error("Localhost runtime currently supports local folder sources only.");throw Object.assign(e,{statusCode:400,code:"LOCAL_RUNTIME_REQUIRES_LOCAL_FOLDER"}),e}return n.resolve(e.source.path)}(e.instance),i=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 As(e))return e;const n=new Error(`No free localhost port found in range ${t}-${Math.min(t+999,65535)}.`);throw Object.assign(n,{statusCode:503,code:"LOCAL_INSTANCE_PORT_UNAVAILABLE"}),n}(),s=n.join(this.paths.dataDir,"local-instances",e.instance.id),a=n.join(s,"logs");let c,d;if(t.mkdirSync(a,{recursive:!0}),this.commandOverride)[c,...d]=this.commandOverride,d=[...d,"--host","127.0.0.1","--port",String(i)];else{const r=this.runtimeRoot(e.instance.id),s=JSON.parse(t.readFileSync(n.join(r,"current","runtime-manifest.json"),"utf8")),o=n.resolve(r,"current",s.entrypoint);c=process.execPath,d=[o,"web","--host","127.0.0.1","--port",String(i)]}const l=t.openSync(n.join(a,"controlled-instance.out.log"),"a"),u=t.openSync(n.join(a,"controlled-instance.err.log"),"a"),m=o.spawn(c,d,{cwd:r,detached:!1,stdio:["ignore",l,u],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",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_WORKSPACE:r,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:s,TASK_HANDOFF_LOG_DIR:a,TASK_HANDOFF_APP_SESSION_PERSIST:"1",TASK_HANDOFF_CODEX_APP_SERVER:process.env.TASK_HANDOFF_CODEX_APP_SERVER||"1",TASK_HANDOFF_WEB_PORT:String(i),TASK_HANDOFF_WEB_HOST:"127.0.0.1",...e.modelEnv||{}}});t.closeSync(l),t.closeSync(u);try{await function(e){return new Promise((t,n)=>{const r=()=>{e.off("error",i),t()},i=t=>{e.off("spawn",r),n(t)};e.once("spawn",r),e.once("error",i)})}(m)}catch(e){const i=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(a,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${c} cwd=${r} error=${i}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${c} in ${r}: ${i}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}this.processByInstanceId.set(e.instance.id,m),m.on("error",e=>{try{t.appendFileSync(n.join(a,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] process error pid=${m.pid??""} error=${e.message}\n`)}catch{}}),m.once("exit",(r,i)=>{this.processByInstanceId.delete(e.instance.id);try{t.appendFileSync(n.join(a,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] exited pid=${m.pid??""} code=${r??""} signal=${i??""}\n`)}catch{}});const p=`http://127.0.0.1:${i}`;return await async function(e,t=3e3){const n=Date.now()+t;for(;Date.now()<n;){try{if((await fetch(`${e}/api/health`)).ok)return!0}catch{}await new Promise(e=>setTimeout(e,100))}return!1}(p),{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown",web:p,api:`${p}/api`},workspace:{mode:"local-bind",status:"pending",path:r},runtime:{kind:"local",workspacePath:r,pid:m.pid,port:i,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local"}}}}async stop(e){return await ws(e.instance,this.processByInstanceId),{status:"stopped",health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e){return await ws(e.instance,this.processByInstanceId),this.start(e)}async delete(e){return this.stop(e)}async check(e){const[t,n]=await Promise.all([zs(this.runCommand,"codex"),zs(this.runCommand,"claude")]);return{status:"online",capabilities:ys({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){const e=Array.from(this.processByInstanceId.values());for(const e of this.processByInstanceId.values())e.killed||e.kill("SIGTERM");this.processByInstanceId.clear(),await Promise.all(e.map(e=>bs(e)))}}class _s{docker;local;constructor(e,t){this.docker=e,this.local=t}forRuntime(e){if("docker"===e.type)return this.docker;if("local"===e.type)return this.local;const t=new Error(`Runtime type ${e.type} is not supported by this node agent.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_TYPE_UNSUPPORTED"}),t}managedAdapters(){return[this.docker,this.local].filter(e=>!1!==e.usesManagedArtifact?.())}async stopAll(){this.local instanceof Ss&&await this.local.stopAll()}}class Ts extends fr{onStored;setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=super.put(Yt.parse({...e,stateRevision:Math.max(e.stateRevision||0,t)+1}));return this.onStored?.(n),n}}class ks{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;models;modelAssignments;modelEnvironments;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,r,i,s){this.paths=e,this.nodeId=t,this.localFolders=new fr(e.localFoldersDir,{schema:pt}),this.nodeRuntimes=new fr(e.nodeRuntimesDir,{schema:Ft}),this.controlledInstances=new Ts(e.controlledInstancesDir,{schema:Yt,sanitize:e=>en(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})}),this.models=new hi(e.nodeModelsDir,t),this.modelAssignments=new gi(e.modelAssignmentsDir),this.modelEnvironments=new pi(e.modelEnvironmentsDir),this.updateJobs=new Vr(e),this.listenerPort=i,this.platform=s,this.containerUrlOverride=r;const o=os();this.node=$t.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(){if(this.localFolders.init(),this.nodeRuntimes.init(),this.controlledInstances.init(),this.normalizeInstanceRuntimeVersions(),this.models.init(),this.modelAssignments.init(),this.migrateLegacyModelEnvironments(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),Yi()),!this.nodeRuntimes.get("runtime_local_docker")){const e=os();this.nodeRuntimes.put(Ft.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(Ui),t=os();this.nodeRuntimes.put(Ft.parse({id:Ui,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:ys(e?.capabilities),labels:{...e?.labels,[Vi]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(Ft.parse({...e,nodeId:this.nodeId,updatedAt:os()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(pt.parse({...e,nodeId:this.nodeId,updatedAt:os()}))}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=Xi(e.build?.packageVersion||e.instanceVersion),n=["created","stopped","failed"].includes(e.status),r=e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,i="matched"===t.phase?n?t:{...t,phase:"verifying",matchedAt:void 0}:"failed"===r?.phase&&!1===r.error?.retryable?{...t,phase:"failed",attempt:r.attempt,lastAttemptAt:r.lastAttemptAt,error:r.error}:{...t,attempt:r?.attempt||0,lastAttemptAt:r?.lastAttemptAt};this.controlledInstances.put(Yt.parse({...e,ready:!1,runtimeVersion:i,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=pt.parse({...e,id:e.id||hr("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=Ft.parse({...e,id:e.id||hr("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(r=e.type,"docker"===r?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:Bi(e.labels),createdAt:t,updatedAt:t});var r;return this.nodeRuntimes.put(n)}updateRuntime(e,t){const n=this.requireRuntime(e);if("true"===n.labels[Vi]){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 r=Ft.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?Bi(t.labels):n.labels,createdAt:n.createdAt,updatedAt:os()});return this.nodeRuntimes.put(r)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[Vi]){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=Ft.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:os()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(Ft.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=Qt(t);if(!n.success)throw function(e,t){const n=t.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; "),r=new Error(`Stored instance ${e} is not compatible with protocol ${be}: ${n}`);return Object.assign(r,{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"}),r}(e,n.error.issues);return n.data}listInstances(){return this.controlledInstances.list().flatMap(e=>{const t=Qt(e);return t.success?[t.data]:[]})}listModels(){const e=new Map;for(const t of this.listInstances()){const n=this.modelAssignments.get(t.id);for(const t of[n?.codexModelHash,n?.claudeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.publicModel(t,e.get(t.id)||0))}createModel(e){const t=os(),n=Ct(e),r=this.models.get(n),i=At.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextModelOrder(),labels:e.labels||{},createdAt:r?.createdAt||t,updatedAt:t});return this.publicModel(this.models.put(i),this.modelReferenceIds(n).length)}deployModel(e){const t=Ct(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(At.parse(e));return this.publicModel(n,this.modelReferenceIds(n.id).length)}updateModel(e,t){const n=this.requireModel(e),r=At.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:os()}),i=Ct(r),s=this.models.put(At.parse({...r,id:i}));return this.publicModel(s,this.modelReferenceIds(i).length)}deleteModel(e){this.requireModel(e);const t=this.modelReferenceIds(e);if(t.length)throw Object.assign(new Error(`Model ${e} is assigned to ${t.length} instance${1===t.length?"":"s"}.`),{statusCode:409,code:"NODE_MODEL_IN_USE",instanceIds:t});return this.models.delete(e)}assignModels(e,t){const n=this.requireInstance(e);if(this.validateAssignmentRef("codex",t.codexModelHash),this.validateAssignmentRef("claude",t.claudeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const r=this.modelAssignments.get(e),i=Nt.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:os()});this.modelAssignments.put(i);try{return{assignment:i,instance:this.controlledInstances.put(Yt.parse({...n,modelSelection:t.modelSelection,updatedAt:os()}))}}catch(t){throw r?this.modelAssignments.put(r):this.modelAssignments.delete(e),t}}resolvedAssignedModelEnvironment(e){const t=this.modelAssignments.get(e);if(!t){if(this.modelEnvironments.has(e))throw Object.assign(new Error(`Legacy model environment for instance ${e} requires manual migration.`),{statusCode:409,code:"NODE_MODEL_MIGRATION_REQUIRED"});return{}}return{...this.modelEnvironmentForRef("codex",t.codexModelHash),...this.modelEnvironmentForRef("claude",t.claudeModelHash)}}validateAssignmentRef(e,t){if(!t)return;const n=this.requireModel(t);if(n.app!==e)throw Object.assign(new Error(`Model ${n.id} belongs to ${n.app}, not ${e}.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}modelEnvironmentForRef(e,t){if(!t)return{};this.validateAssignmentRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(Ct(t)!==t.id)throw Object.assign(new Error(`Stored model ${e} does not match its content hash.`),{statusCode:409,code:"NODE_MODEL_HASH_INVALID"});return t}modelReferenceIds(e){return this.listInstances().filter(t=>{const n=this.modelAssignments.get(t.id);return n?.codexModelHash===e||n?.claudeModelHash===e}).map(e=>e.id)}publicModel(e,t){const{key:n,...r}=e;return wt.parse({...r,keyPreview:n.length<=8?"set":`${n.slice(0,4)}...${n.slice(-4)}`,keySet:!0,referenceCount:t})}nextModelOrder(){return this.models.list().reduce((e,t)=>Math.max(e,t.order),0)+100}migrateLegacyModelEnvironments(){for(const e of this.modelEnvironments.listInstanceIds()){if(!this.controlledInstances.get(e)){this.warnLegacyModelMigration(e,"instance-not-found");continue}if(this.modelAssignments.get(e)){try{this.resolvedAssignedModelEnvironment(e),this.modelEnvironments.delete(e)}catch{this.warnLegacyModelMigration(e,"existing-assignment-invalid")}continue}let t;try{t=this.modelEnvironments.get(e)}catch{this.warnLegacyModelMigration(e,"sidecar-invalid");continue}if(!Object.keys(t).length){this.modelEnvironments.delete(e);continue}if(Object.keys(t).some(e=>!mi.has(e))){this.warnLegacyModelMigration(e,"unknown-fields");continue}const n=[];try{const r=this.migrateLegacyModelForApp(t,"codex",n),i=this.migrateLegacyModelForApp(t,"claude",n);if(!r&&!i)throw new Error("no complete model configuration");const s={...r?{codexModelHash:r}:{},...i?{claudeModelHash:i}:{}};this.assignModels(e,{modelSelection:s,codexModelHash:r,claudeModelHash:i}),this.resolvedAssignedModelEnvironment(e),this.modelEnvironments.delete(e)}catch{this.modelAssignments.delete(e);for(const e of n)this.models.delete(e);this.warnLegacyModelMigration(e,"mapping-failed")}}}migrateLegacyModelForApp(e,t,n){const r=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],i="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,s="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!Boolean(r||i||s))return;if(!r||!i||!s)throw new Error("model configuration incomplete");const o=Ct({app:t,endpoint:i,key:r,model:s}),a=this.models.get(o);if(a){if(a.app!==t||a.key!==r||a.endpoint!==i||a.model!==s||!a.enabled)throw new Error("existing model conflicts with legacy environment");return o}const c=os();return this.models.put(At.parse({id:o,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:i,key:r,model:s,app:t,enabled:!0,order:this.nextModelOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(o),o}warnLegacyModelMigration(e,t){console.warn(JSON.stringify({message:"legacy model environment was preserved because it could not be migrated",nodeId:this.nodeId,instanceId:e,reason:t}))}createInstance(e){const t=this.requireRuntime(e.runtimeId),r=os(),i=e.id||hr("inst"),s=ht.parse(e.source);if(function(e){return"boolean"==typeof e.capabilities.requiresImage?e.capabilities.requiresImage:"local"!==e.type}(t)&&(!e.imageId||!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?xt.parse(e.image):void 0,a=o?(()=>{const{reference:e,...t}=o;return Ot.parse({...t,requestedReference:e})})():void 0,c="local"===t.type&&"local-folder"===s.type?n.resolve(s.path):void 0,d=Yt.parse({id:i,name:e.name||`instance-${i.replace(/^inst_?/,"").slice(0,6)}`,source:s,sourceSnapshot:e.sourceSnapshot||{},modelSelection:e.modelSelection,projectId:e.projectId,nodeId:this.nodeId,runtimeId:t.id,imageId:o?.id,imageSnapshot:a,imageProvisioning:a&&"docker"===t.type?{phase:"checking-image",requestedReference:a.requestedReference,generation:0,startedAt:r,updatedAt:r}:void 0,status:a&&"docker"===t.type?"provisioning":"created",health:"unknown",connectionStatus:"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",controlMode:"controlled",ready:!1,runtimeVersion:Xi(),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:c}:{status:"unknown"},target:{strategy:"node-proxy",status:"unknown"},runtime:"local"===t.type?{kind:"local",workspacePath:c,labels:{"task-handoff.runtime-kind":"local"}}:{labels:{}},registrationToken:gr(),createdAt:r,updatedAt:r});return this.controlledInstances.put(d)}registerInstance(e,t,n){const r=sn.parse(t),i=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}this.validateInstanceReport(s,r,n),Is(r.protocolVersion,`Instance ${e}`);const o=r.build?.packageVersion||r.instanceVersion,a=Zi(s,o),c=Yt.parse({...s,name:r.name,status:"registered",health:o===Yi()?"ok":"degraded",ready:!1,connectionStatus:"online",agentStatus:"online",targetStatus:"endpoint-unreachable"===r.target.status?"endpoint-unreachable":"reachable"===r.target.status?"reachable":s.targetStatus,uiAccessStatus:"endpoint-unreachable"===r.target.status?"endpoint-unreachable":s.uiAccessStatus,controlMode:r.controlMode,protocolVersion:r.protocolVersion,instanceVersion:r.instanceVersion,build:r.build,runtimeVersion:a,capabilities:r.capabilities,appInventory:r.appInventory,workspace:r.workspace,target:{...s.target,...r.target},registrationToken:s.registrationToken||r.registrationToken,lastHeartbeatAt:i,updatedAt:i});return this.controlledInstances.put(c)}heartbeatInstance(e,t,n){const r=this.requireInstance(e);this.validateInstanceToken(r,n);const i=on.parse(t);Is(i.protocolVersion,`Instance ${e}`);const s=os(),o=i.target?{...r.target,...i.target}:r.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":r.targetStatus,d=i.build?.packageVersion||r.build?.packageVersion||r.instanceVersion,l=Zi(r,d),u=r.ready&&"matched"===r.runtimeVersion?.phase&&d===Yi(),m=Yt.parse({...r,...i,target:a,ready:u&&"failed"!==i.health,health:d===Yi()?i.health||r.health:"degraded",runtimeVersion:l,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:i.build||r.build,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.put(m)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&fs("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&fs("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&fs("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageId&&t.imageId!==e.imageId&&fs("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||fs("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||Ot.parse({id:e.imageId||"img_localhost",name:e.imageId||"Localhost",requestedReference:"localhost:local",pullPolicy:"if-not-present",capabilities:[],optionalApps:[],defaultEnv:{},labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt});return{project:ls(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t}}}class Cs{app;state;settings;sockets=new Set;config;source;status="error";error;constructor(e){this.app=e.app,this.state=e.state,this.settings=e.settings,this.config=e.config,this.source=e.source,this.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return Ht.parse({...this.config,host:as(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:as(this.config.bindScope),port:this.config.port,error:this.error},"node agent TCP listener failed to start; Unix IPC remains available")}return this.current()}async update(e){const t=qt.parse(e);if(t.bindScope===this.config.bindScope&&t.port===this.config.port)return this.current();if(t.port!==this.config.port){const e=this.state.runningInstanceCount();if(e>0){const t=new Error(`Cannot change the node agent port while ${e} controlled instance(s) are running.`);throw Object.assign(t,{statusCode:409,code:"NODE_AGENT_LISTENER_PORT_IN_USE_BY_INSTANCES",blockingInstanceCount:e}),t}}const n={config:this.config,source:this.source,status:this.status,error:this.error};await this.stop();try{await this.listen(t)}catch(e){await this.restore(n);const r=new Error(`Failed to bind node agent TCP listener at ${as(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`);throw Object.assign(r,{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"}),r}try{this.settings.put({version:1,externalListener:t})}catch(e){await this.stop(),await this.restore(n);const t=new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`);throw Object.assign(t,{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"}),t}return this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port),this.current()}async shutdown(){await this.stop()}async restore(e){if(this.config=e.config,this.source=e.source,this.status=e.status,this.error=e.error,"listening"===e.status)try{await this.listen(e.config)}catch(e){this.status="error",this.error=`Failed to restore previous listener: ${e instanceof Error?e.message:String(e)}`,this.app.log.error({error:this.error},"node agent TCP listener rollback failed")}this.state.setListenerPort(e.config.port)}async listen(e){await new Promise((t,n)=>{const r=e=>{this.app.server.off("listening",i),n(e)},i=()=>{this.app.server.off("error",r),t()};this.app.server.once("error",r),this.app.server.once("listening",i),this.app.server.listen({host:as(e.bindScope),port:e.port})})}async stop(){this.app.server.listening&&await new Promise((e,t)=>{this.app.server.close(n=>n?t(n):e());for(const e of this.sockets)e.destroy()})}}async function xs(e,t,n,r,i,s="request"){const o=e.requireInstance(r);if(o.imageProvisioning&&"ready"!==o.imageProvisioning.phase&&"docker"===e.requireRuntime(o.runtimeId).type)return i.diagnostic({instanceId:r,action:"start",reason:s,runtimeId:o.runtimeId,imageId:o.imageId,imagePhase:o.imageProvisioning.phase},"node instance start queued until image provisioning completes"),e.controlledInstances.put(Yt.parse({...o,status:"starting",updatedAt:os()}));i.diagnostic({instanceId:r,action:"start",reason:s,runtimeId:o.runtimeId,imageId:o.imageId},"node instance start requested");const a=e.controlledInstances.put(Yt.parse({...o,status:"starting",ready:!1,updatedAt:os()})),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await us(n,Yt.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:os()})),u=Os(a,e.requireInstance(r),{...d,target:d.target?{...d.target,status:l}:void 0,workspace:d.workspace?{error:void 0,...d.workspace}:void 0,targetStatus:l,uiAccessStatus:l}),m=e.controlledInstances.put(u);return i.diagnostic({instanceId:r,action:"start",reason:s,status:m.status,connectionStatus:m.connectionStatus,targetStatus:m.targetStatus,targetWeb:m.target.web,containerName:m.runtime.containerName},"node instance start completed"),m}function Os(e,t,n){const r=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return Yt.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:os()})}function Rs(e,t){const n=t instanceof Error?t.message:String(t);return Yt.parse({...e,status:"failed",ready:!1,health:"failed",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",workspace:{...e.workspace,error:n},updatedAt:os()})}function Ds(e){return Yt.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:os()})}async function js(e={}){const r=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,i=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),o=`http://127.0.0.1:${i}`,m=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,p=cr(e.dataDir),h=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,g=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,I=new Mi(p),y=I.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),A=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),w=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||Or(p.dataDir),N="local-ipc"===A?`ipc://${encodeURIComponent(w)}`:o,z=e.platform||process.platform,v=e.arch||process.arch,E=new ks(p,y,o,m,i,z);E.node.connectionMode=A,E.node.controlEndpoint=N,E.node.endpoint=N,E.init();const S=e.dockerCommandRunner||mn,_=new hn(S,e.dockerTerminalCommandRunner),T=new gn(S,{publishHost:"127.0.0.1",imageService:_}),k=new _s(new Es(T,S,z,v),new Ss(e.dockerCommandRunner||mn,p,()=>E.localNodeAgentUrl,z,v,e.allowUnmanagedLocalCommandOverride?function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e)return;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}():void 0)),C=e.updateCommandRunner||e.dockerCommandRunner||mn,x=e.fetchImpl||fetch,O=new Qr({cacheDir:n.join(p.dataDir,"runtime-artifacts"),fetchImpl:x}),R=e.resolveRuntimeArtifactRelease||((e,t,n)=>ti(e,t,n,x)),D=async(t,n,r)=>{const i=await n.artifactTarget(r);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,i.platform,i.arch);const s=await R(t,i.platform,i.arch);if(s.identity.launcherAbi>i.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${s.identity.launcherAbi}, but ${i.platform}-${i.arch} provides ABI ${i.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return O.resolve(s.identity,s.source)},j=e=>k.forRuntime(E.requireRuntime(e.runtimeId)),P=e=>!1!==j(e).usesManagedArtifact?.(),M=(e,t)=>{const n=E.context(e);return D(t,j(e),n)},L=c({logger:e.logger??!0}),$={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:ns()};L.decorate("nodeAgentState",E),await L.register(d);const F=new Pn(E,r,{logger:L.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),U=new ni(E.controlledInstances,Yi,{isInstalled:async(e,t)=>{const n=await M(e,t);return j(e).inspectRuntime(E.context(e),n.identity)},install:async(e,t)=>{const n=j(e);await n.installRuntime(E.context(e),await M(e,t))},restart:async e=>{const t=j(e),n=E.requireInstance(e.id),r=E.controlledInstances.put(Yt.parse({...n,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:os()})),i=await t.restart(E.context(r)),s=E.requireInstance(e.id);E.controlledInstances.put(Os(r,s,i))},rollback:async e=>j(e).rollbackRuntime(E.context(e)),onForcedDrain:e=>L.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=>{F.publishInstanceLifecycle(e),E.updateJobs.reconcileRollouts(E.listInstances(),Yi())}),F.start();for(const e of E.listInstances())P(e)&&!["created","stopped","failed","provisioning"].includes(e.status)&&U.schedule(e.id).catch(t=>L.log.error({instanceId:e.id,error:t},"runtime convergence recovery failed"));L.decorate("nodeAgentEventForwarder",F);const V=new Hn(S,()=>E.listInstances().filter(e=>"docker"===E.requireRuntime(e.runtimeId).type),e=>F.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));V.start(),L.decorate("nodeAgentRuntimeMetrics",V);const H=(Q=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(Q||"").trim().toLowerCase())),q=new fi(I,y,h,g),B=(e,t)=>{H&&L.log.info(e,t)},K={diagnostic:B,warn:(e,t)=>L.log.warn(e,t)},G=async(e,t)=>{try{let t=E.requireInstance(e);"failed"===t.runtimeVersion?.phase&&P(t)&&(t=E.controlledInstances.put(Yt.parse({...t,ready:!1,runtimeVersion:Xi(ri(t)),updatedAt:os()})));const n=E.requireRuntime(t.runtimeId);"local"===n.type&&P(t)?E.controlledInstances.put(Yt.parse({...t,status:"starting",ready:!1,updatedAt:os()})):await xs(E,k,x,e,K);const r=E.requireInstance(e);if("docker"===n.type&&"ready"!==r.imageProvisioning?.phase)return F.syncNow(),r;const i=P(E.requireInstance(e))?await U.schedule(e,{startRequested:!0}):E.requireInstance(e);if("failed"===i.runtimeVersion?.phase)throw Object.assign(new Error(i.runtimeVersion.error?.message||`Instance ${e} runtime convergence failed.`),{statusCode:503,...i.runtimeVersion.error||{code:"INSTANCE_RUNTIME_INSTALL_FAILED",retryable:!0}});return await ps(x,i,"start",K),F.syncNow(),i}catch(n){const r=Rs(E.requireInstance(e),n);throw E.controlledInstances.put(r),F.syncNow(),K.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},J=e=>{e.imageProvisioning&&async function(t,n,r,i,s,o,a){const c=e=>{const n=t.controlledInstances.get(r);n&&n.imageProvisioning?.generation===i&&n.imageSnapshot&&(t.controlledInstances.put(Yt.parse({...n,status:"starting"===n.status?"starting":"provisioning",imageProvisioning:{...n.imageProvisioning,phase:e,error:void 0,updatedAt:os()},updatedAt:os()})),s())},d=t.controlledInstances.get(r);if(!d?.imageSnapshot||d.imageProvisioning?.generation!==i)return;let l=0,u=!1;try{const m=await n.ensure(d.imageSnapshot.requestedReference,c,e=>{u=!0,l=e.sequence,a?.(e)});u&&a?.({sequence:l+1,outcome:"succeeded"});const p=t.controlledInstances.get(r);if(!p?.imageSnapshot||p.imageProvisioning?.generation!==i)return;t.controlledInstances.put(Yt.parse({...p,status:"starting"===p.status?"starting":"created",health:"unknown",imageSnapshot:{...p.imageSnapshot,requestedReference:m.requestedReference,resolvedDigest:m.resolvedDigest,resolvedReference:m.resolvedReference},imageProvisioning:{...p.imageProvisioning,phase:"ready",error:void 0,updatedAt:os()},updatedAt:os()})),s(),o.diagnostic({instanceId:r,action:"image.provision",reference:m.requestedReference,digest:m.resolvedDigest,pulled:m.pulled},"node instance image provisioning completed"),"starting"===p.status&&await((async e=>{await G(e,"image-ready").catch(()=>{})})(e.id))}catch(e){u&&a?.({sequence:l+1,outcome:"failed"});const n=t.controlledInstances.get(r);if(!n?.imageProvisioning||n.imageProvisioning.generation!==i)return;const c=e instanceof Error?e.message:String(e);t.controlledInstances.put(Yt.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:c,updatedAt:os()},updatedAt:os()})),s(),o.warn({instanceId:r,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:c},"node instance image provisioning failed")}}(E,_,e.id,e.imageProvisioning.generation,()=>F.syncNow(),K,t=>{const n={instanceId:e.id,generation:e.imageProvisioning.generation,requestedReference:e.imageProvisioning.requestedReference,observedAt:os()};if("outcome"in t)F.publish(jt,{...n,sequence:1e3*t.sequence,outcome:t.outcome},{instanceId:e.id});else for(const[r,i]of function(e,t=6e4){const n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}(t.data).entries())F.publish(Dt,{...n,sequence:1e3*t.sequence+r,data:i,...t.replay?{replay:!0}:{}},{instanceId:e.id})})},W=async e=>{const t=new Map;for(const e of k.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of E.listInstances()){if(!P(e))continue;const n=j(e),r=E.context(e),i=await n.artifactTarget(r);t.set(`${i.platform}-${i.arch}`,{adapter:n,context:r})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>D(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))},Y=async e=>{const t=X(),n=await async function(e){const t=await async function(e,t,n){const r=function(e){return"stable"===e?"latest":e}(n),i=await e(Fr(),["view",`${t}@${r}`,"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(!i)return;const s=JSON.parse(i.stdout);if("string"!=typeof s)throw new Error(`npm did not resolve ${t}@${r} to one version.`);return s}(e.runCommand,"@task-handoff/node-agent",e.channel);if(!t)return function(e){return at.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:$r()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const n=function(e,t){if(!e)return!0;const n=f.valid(e),r=f.valid(t);return n&&r?f.gt(r,n):e!==t}(e.currentVersion,t),r=n?await async function(e,t,n){const r=await e(Fr(),["view",`${t}@${n}`,"dist.integrity","--json"]),i=JSON.parse(r.stdout);if("string"!=typeof i||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(i))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 i}(e.runCommand,"@task-handoff/node-agent",t):void 0;return at.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:t,...r?{artifactRef:`npm:@task-handoff/node-agent@${t}#${r}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:n,checkedAt:$r()})}({channel:e.channel,currentVersion:Yi(),runCommand:C,impact:t});if(!n.updateAvailable)return n;const r=await W(n.availableVersion),i={...n,runtimeArtifacts:r.map(e=>e.identity),preflightToken:gr()};return Z.set(i.preflightToken,{result:i,expiresAt:Date.now()+6e5}),i},X=()=>{const e=E.listInstances(),t=e.filter(e=>!["created","stopped","failed"].includes(e.status)),n=t.filter(e=>e.apps.runningCount>0||e.aiSessions.runningCount>0);return{runningInstanceCount:t.length,stoppedInstanceCount:e.length-t.length,activeInstanceCount:n.length,restartInstanceCount:t.length,runningInstanceIds:t.map(e=>e.id).sort(),stoppedInstanceIds:e.filter(e=>!t.includes(e)).map(e=>e.id).sort(),activeInstanceIds:n.map(e=>e.id).sort()}},Z=new Map;var Q;L.setErrorHandler((e,t,n)=>{const r=function(e){if(e instanceof u.z.ZodError)return{statusCode:400,code:"VALIDATION_ERROR",message:e.issues.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; ")};const t=e&&"object"==typeof e?e:{};return{statusCode:"number"==typeof t.statusCode?t.statusCode:500,code:"string"==typeof t.code?t.code:"NODE_AGENT_ERROR",message:e instanceof Error?e.message:String(e)}}(e);(H||r.statusCode>=500)&&(r.statusCode>=500?L.log.error.bind(L.log):L.log.warn.bind(L.log))({method:t.method,url:t.url,statusCode:r.statusCode,errorCode:r.code,error:r.message},"node agent request failed"),n.code(r.statusCode).send({error:{code:r.code,message:r.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}:{}}})}),L.addHook("preHandler",async e=>{const t=q.verify(e);if(t)e.nodeAgentAuthKeyId=t;else if(ss(e)){if(r&&rs(e.headers)!==r){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(q.hasRemoteSecrets()){const e=new Error("Node agent HMAC signature is required.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_REQUIRED"}),e}if(!function(e){return is(e.ip)||is(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(r&&rs(e.headers)!==r){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),L.addHook("onClose",async()=>{V.stop(),F.stop();for(const e of E.listInstances())U.cancel(e.id);await async function(e,t){await t.stopAll();for(const t of e.listInstances())"local"===e.requireRuntime(t.runtimeId).type&&e.controlledInstances.put(Ds(t))}(E,k)}),L.decorate("nodeAgentRestoreLocalInstances",async()=>{for(const e of E.listInstances().filter(e=>["provisioning","starting"].includes(e.status)&&"ready"!==e.imageProvisioning?.phase&&"docker"===E.requireRuntime(e.runtimeId).type))J(e);const e=E.listInstances().filter(e=>"local"===E.requireRuntime(e.runtimeId).type&&Ns.has(e.status));for(const t of e)try{P(t)?(E.controlledInstances.put(Yt.parse({...t,status:"starting",ready:!1,updatedAt:os()})),await U.schedule(t.id,{startRequested:!0})):await xs(E,k,x,t.id,K,"restore"),await ps(x,E.requireInstance(t.id),"start",K)}catch(e){E.controlledInstances.put(Rs(E.requireInstance(t.id),e)),B({instanceId:t.id,action:"restore",error:e instanceof Error?e.message:String(e)},"node local instance restore failed")}}),L.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",nodeId:y,platform:qi(z),protocolVersion:be,build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:Yi(),protocolVersion:be,buildId:Wi("TASK_HANDOFF_BUILD_ID"),builtAt:Wi("TASK_HANDOFF_BUILT_AT"),gitCommit:Wi("TASK_HANDOFF_GIT_COMMIT"),imageRef:Wi("TASK_HANDOFF_IMAGE_REF"),imageDigest:Wi("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...$},serverTime:(new Date).toISOString()}};var e});const ee=e=>{if(!ss(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(!L.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 L.nodeAgentListenerManager};return L.get("/api/node-agent/settings/external-listener",async e=>({data:ee(e).current()})),L.patch("/api/node-agent/settings/external-listener",async e=>({data:await ee(e).update(e.body)})),L.get("/api/node-agent/updates/jobs",async()=>({data:E.updateJobs.list()})),L.post("/api/node-agent/updates/check",async e=>({data:await Y(ot.parse(e.body))})),L.post("/api/node-agent/updates/apply",async(e,r)=>{const i=Ji.parse(e.body),o=await(async e=>{const t=Z.get(e.preflightToken);if(Z.delete(e.preflightToken),!t||t.expiresAt<=Date.now()){const e=new Error("The update preflight is missing or expired. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_EXPIRED"}),e}const n=t.result;if(n.channel!==e.channel||n.availableVersion!==e.targetVersion||n.currentVersion!==Yi()||JSON.stringify(n.impact)!==JSON.stringify(X())){const e=new Error("The update target or affected instances changed after preflight. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"}),e}const r=await W(n.availableVersion);if(JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(r.map(e=>e.identity))){const e=new Error("The runtime artifacts changed after preflight. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"}),e}return n})(i);if(!o.supported){const e=new Error(o.reason||"The requested update is not supported.");throw Object.assign(e,{statusCode:400,code:"UPDATE_UNSUPPORTED"}),e}if(!o.updateAvailable){const e=new Error(o.reason||"No update is available for the selected channel.");throw Object.assign(e,{statusCode:409,code:"UPDATE_NOT_AVAILABLE"}),e}const a=E.updateJobs.create(y,o),c=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,{worker:d,packaged:l,expectedWorker:u}=function(e,r=t.existsSync){const i=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],s=i.find(r),o=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cjs");return s?{worker:s,packaged:!0,expectedWorker:i[0]}:r(o)?{worker:o,packaged:!1,expectedWorker:i[0]}:{worker:void 0,packaged:!1,expectedWorker:i[0]}}(c);if(!d){E.updateJobs.patch(a.id,{status:"failed",rollout:{...a.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Update worker was not found: ${u}`,retryable:!1},completedAt:os()});const e=new Error(`Node agent update worker was not found: ${u}`);throw Object.assign(e,{statusCode:500,code:"UPDATE_WORKER_NOT_FOUND"}),e}return await C("systemd-run",["--unit",`task-handoff-update-${a.id}`,"--collect","--property=Type=exec",...l?[d]:[process.execPath,d],"--job-file",E.updateJobs.records.filePath(a.id),"--target-version",a.toVersion,"--npm-command",Fr()]),r.code(202).send({data:a})}),L.post("/api/node-agent/pairing/invites",async(e,t)=>{const n=I.createPairingInvite(zi.parse(e.body||{}));return t.code(201).send({data:{nodeId:y,joinToken:n.token,expiresAt:n.expiresAt}})}),L.post("/api/node-agent/pairing/complete",async(e,t)=>{const n=I.completePairingInvite(vi.parse(e.body));return t.code(201).send({data:{nodeId:y,keyId:n.keyId,secret:n.secret,pairedAt:n.pairedAt}})}),L.get("/api/node-agent/remotes",async e=>({data:I.listRemoteControlPlanes(e.nodeAgentAuthKeyId)})),L.delete("/api/node-agent/remotes/:keyId",async e=>{const t=u.z.string().trim().min(1).max(160).parse(e.params.keyId);return{data:{deleted:I.deleteRemoteControlPlane(t,e.nodeAgentAuthKeyId)}}}),L.post("/api/node-agent/remotes/connect",async(e,t)=>{const n=Ei.parse(e.body),r=function(e){const t=new URL(e);if("http:"!==t.protocol&&"https:"!==t.protocol){const e=new Error("Control-plane URL must use http or https.");throw Object.assign(e,{statusCode:400,code:"NODE_AGENT_REMOTE_CONTROL_PLANE_URL_INVALID"}),e}return t.toString().replace(/\/$/,"")}(n.controlPlaneUrl),i=I.createRemoteControlPlane({url:r,...n.controlPlaneName?{name:n.controlPlaneName}:{},active:!1!==n.activate}),s=await async function(e,t,n){const r=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),i=await r.json().catch(()=>({}));if(!r.ok){const e=new Error(i.error?.message||`Control-plane node join failed with HTTP ${r.status}.`);throw Object.assign(e,{statusCode:r.status,code:i.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return i.data||{}}(x,r,{joinToken:n.joinToken,nodeId:y,nodeName:E.node.name,keyId:i.keyId,secret:i.secret,pairedAt:i.pairedAt}),o=I.upsertRemoteControlPlane({...i,..."string"==typeof s.name&&s.name?{name:n.controlPlaneName||s.name}:{}});let a,c=!1!==o.active?"saved":"disabled";if(!1!==o.active&&L.nodeAgentReverseTunnels)try{L.nodeAgentReverseTunnels.connect({url:r,keyId:o.keyId,secret:o.secret}),c="connecting"}catch(e){c="failed",a=e instanceof Error?e.message:String(e)}return t.code(201).send({data:{remote:{id:o.id,url:o.url,keyId:o.keyId,pairedAt:o.pairedAt,active:!1!==o.active},tunnel:{status:c,...a?{error:a}:{}}}})}),L.get("/api/node-agent/runtimes",async()=>({data:E.nodeRuntimes.list()})),L.post("/api/node-agent/runtimes",async(e,t)=>t.code(201).send({data:E.createRuntime(sr.parse(e.body))})),L.patch("/api/node-agent/runtimes/:id",async e=>({data:E.updateRuntime(e.params.id,or.parse(e.body))})),L.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:E.deleteRuntime(e.params.id)}})),L.post("/api/node-agent/runtimes/:id/check",async e=>{const t=E.requireRuntime(e.params.id);return{data:await E.checkRuntime(t.id,k.forRuntime(t))}}),L.get("/api/node-agent/local-folders",async()=>({data:E.localFolders.list()})),L.get("/api/node-agent/folders/tree",async e=>({data:Qn(nr.parse(e.query))})),L.post("/api/node-agent/local-folders",async(e,t)=>t.code(201).send({data:E.createLocalFolder(tr.parse(e.body))})),L.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:E.localFolders.delete(e.params.id)}})),L.get("/api/node-agent/models",async()=>({data:E.listModels()})),L.post("/api/node-agent/models",async(e,t)=>t.code(201).send({data:E.createModel(St.parse(e.body))})),L.put("/api/node-agent/models/:id/deploy",async e=>{const t=e.params.id,n=Tt.parse(e.body);if(n.id!==t)throw Object.assign(new Error(`Model payload id ${n.id} does not match route id ${t}.`),{statusCode:400,code:"NODE_MODEL_ID_MISMATCH"});return{data:E.deployModel(n)}}),L.patch("/api/node-agent/models/:id",async e=>({data:E.updateModel(e.params.id,_t.parse(e.body))})),L.delete("/api/node-agent/models/:id",async e=>({data:{deleted:E.deleteModel(e.params.id)}})),L.get("/api/node-agent/instances",async()=>({data:E.listInstances()})),L.post("/api/node-agent/instances",async(e,t)=>{const n=E.createInstance(rr.parse(e.body));return F.syncNow(),n.imageProvisioning&&J(n),t.code(201).send({data:n})}),L.post("/api/node-agent/instances/:id/image-provisioning/retry",async e=>{const t=function(e,t){const n=e.requireInstance(t);if("docker"!==e.requireRuntime(n.runtimeId).type||!n.imageSnapshot){const e=new Error(`Instance ${t} does not use a Docker image.`);throw Object.assign(e,{statusCode:400,code:"INSTANCE_IMAGE_PROVISIONING_UNSUPPORTED"}),e}if("failed"!==n.status||"failed"!==n.imageProvisioning?.phase){const e=new Error(`Instance ${t} does not have failed image provisioning to retry.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_IMAGE_PROVISIONING_NOT_FAILED"}),e}const r=os();return e.controlledInstances.put(Yt.parse({...n,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:n.imageSnapshot.requestedReference,generation:(n.imageProvisioning?.generation||0)+1,startedAt:r,updatedAt:r},updatedAt:r}))}(E,e.params.id);return F.syncNow(),J(t),{data:t}}),L.patch("/api/node-agent/instances/:id",async e=>{const t=e.params.id,n=E.requireInstance(t),r=ir.parse(e.body),i=Yt.parse({...n,...r,...r.config?{config:{...n.config,...r.config}}:{},updatedAt:os()}),s=E.controlledInstances.put(i);return F.syncNow(),{data:s}}),L.put("/api/node-agent/instances/:id/model-assignment",async e=>{const t=e.params.id,n=E.assignModels(t,kt.parse(e.body));return await hs(x,E,t),{data:n}}),L.post("/api/node-agent/instances/:id/register",async(e,t)=>{const n=e.params.id,r=E.registerInstance(n,sn.parse(e.body),rs(e.headers));return F.syncNow(),B({instanceId:n,action:"register",protocolVersion:r.protocolVersion,build:r.build,targetStatus:r.targetStatus,targetStrategy:r.target.strategy},"node instance registered"),!P(r)||r.ready&&"matched"===r.runtimeVersion?.phase||U.schedule(n).catch(e=>L.log.error({instanceId:n,error:e},"runtime convergence after registration failed")),t.code(201).send({data:r})}),L.post("/api/node-agent/instances/:id/heartbeat",async e=>{const t=e.params.id,n=E.heartbeatInstance(t,on.parse(e.body),rs(e.headers));return F.syncNow(),B({instanceId:t,action:"heartbeat",status:n.status,health:n.health,protocolVersion:n.protocolVersion,build:n.build,targetStatus:n.targetStatus,apps:n.apps.runningCount},"node instance heartbeat accepted"),!P(n)||n.ready&&"matched"===n.runtimeVersion?.phase||U.schedule(t).catch(e=>L.log.error({instanceId:t,error:e},"runtime convergence after heartbeat failed")),{data:n}}),L.get("/api/node-agent/events",{websocket:!0},e=>{const t=e;t.send(JSON.stringify({type:"node-agent.events.connected",nodeId:y,serverTime:(new Date).toISOString()}));const n=F.addOutput(t);t.on("close",n),t.on("error",n)}),L.get("/api/node-agent/docker/images",async()=>({data:await yn(e.dockerCommandRunner)})),L.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 V.snapshot(t)}}),L.post("/api/node-agent/instances/:id/start",async e=>{const t=e.params.id;return Gi.parse(e.body),{data:await G(t,"request")}}),L.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const t=e.params.id;Gi.parse(e.body);const n=E.requireInstance(t);E.controlledInstances.put(Yt.parse({...n,ready:!1,runtimeVersion:Xi(ri(n)),updatedAt:os()}));const r=await U.schedule(t,{startRequested:!["created","stopped"].includes(n.status),resumeCancelled:!0});return F.syncNow(),{data:r}}),L.post("/api/node-agent/instances/:id/stop",async e=>{const t=e.params.id;await U.cancel(t);const n=E.requireInstance(t);B({instanceId:n.id,action:"stop",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance stop requested");const r=k.forRuntime(E.requireRuntime(n.runtimeId)),i=await r.stop(E.context(n)),s=Yt.parse({...n,...i,ready:!1,agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",updatedAt:os()}),o=E.controlledInstances.put(s);return F.syncNow(),B({instanceId:n.id,action:"stop",status:o.status,connectionStatus:o.connectionStatus,containerName:o.runtime.containerName},"node instance stop completed"),{data:o}}),L.post("/api/node-agent/instances/:id/restart",async e=>{const t=e.params.id,n=E.requireInstance(t);if(Gi.parse(e.body),P(n)&&(!n.ready||"matched"!==n.runtimeVersion?.phase)){const e=await U.schedule(t,{startRequested:!0});return F.syncNow(),{data:e}}B({instanceId:t,action:"restart",runtimeId:n.runtimeId,imageId:n.imageId,containerName:n.runtime.containerName},"node instance restart requested");const r=k.forRuntime(E.requireRuntime(n.runtimeId)),i=await r.restart(E.context(n)),s=Yt.parse({...n,...i,target:i.target?{...n.target,...i.target}:n.target,updatedAt:os()}),o=await us(x,s),a=Os(n,E.requireInstance(t),{...i,target:i.target?{...i.target,status:o}:void 0,targetStatus:o,uiAccessStatus:o}),c=E.controlledInstances.put(a);return await ps(x,c,"restart",K),F.syncNow(),B({instanceId:t,action:"restart",status:c.status,connectionStatus:c.connectionStatus,targetStatus:c.targetStatus,targetWeb:c.target.web,containerName:c.runtime.containerName},"node instance restart completed"),{data:c}}),L.post("/api/node-agent/instances/:id/delete",async e=>{const t=e.params.id,n=E.requireInstance(t);await U.cancel(t),B({instanceId:t,action:"delete",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance delete requested");const r=k.forRuntime(E.requireRuntime(n.runtimeId));await r.delete(E.context(n,{})),B({instanceId:t,action:"delete"},"node instance delete completed");const i=E.controlledInstances.delete(t);return E.modelAssignments.delete(t),E.modelEnvironments.delete(t),F.syncNow(),{data:{deleted:i}}}),L.post("/api/node-agent/instances/:id/proxy",async(e,t)=>{const n=e.params.id,r=er.parse(e.body),i=gs(E.requireInstance(n)),s=r.path.startsWith("/")?r.path:`/${r.path}`;"POST"===r.method&&"/api/apps/sessions"===s&&await hs(x,E,n),B({instanceId:n,action:"proxy",method:r.method,path:s,instanceBase:i},"node instance proxy requested");const o=await x(`${i}${s}`,{method:r.method,headers:{...r.headers},body:es(r)}),a=o.headers.get("content-type")||"application/octet-stream",c=await o.text();B({instanceId:n,action:"proxy",method:r.method,path:s,statusCode:o.status,contentType:a},"node instance proxy completed"),t.code(o.status).type(a).send(c)}),L.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:ts},async(e,t)=>{const n=Date.now();$.requests+=1,$.active+=1;const r=new AbortController;let i=0,s=!1,o=!1;const c=e=>{o||(o=!0,$.active-=1,$.totalDurationMs+=Date.now()-n,$.responseBytes+=i,$[e]+=1)},d=()=>{r.abort(),s&&c("aborted")};e.raw.once("aborted",d),t.raw.once("close",d);try{const n=e.params.id,o=er.parse(e.body),d=gs(E.requireInstance(n)),l=o.path.startsWith("/")?o.path:`/${o.path}`;B({instanceId:n,action:"proxy.stream",method:o.method,path:l,instanceBase:d},"node instance streaming proxy requested");const u=await x(`${d}${l}`,{method:o.method,headers:{...o.headers},body:es(o),signal:r.signal}),m=Number(u.headers.get("content-length"));if(Number.isFinite(m)&&m>$.maxResponseBytes)return $.limitRejected+=1,r.abort(),t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${$.maxResponseBytes} bytes.`}});t.code(u.status);for(const[e,n]of Object.entries(Qi(u.headers)))t.header(e,n);if(!u.body||"HEAD"===o.method)return c("completed"),t.send();const p=new a.Transform({transform(e,t,n){if(i+=e.length,i>$.maxResponseBytes)return $.limitRejected+=1,r.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return s=!0,p.once("end",()=>c("completed")),p.once("error",()=>c("aborted")),t.send(a.Readable.fromWeb(u.body).pipe(p))}catch(e){throw c("aborted"),e}finally{e.raw.off("aborted",d),s||c("completed")}}),L.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:ts},async(e,t)=>{const n=e.params.id,r=er.parse(e.body),i=gs(E.requireInstance(n)),s=r.path.startsWith("/")?r.path:`/${r.path}`;B({instanceId:n,action:"proxy.raw",method:r.method,path:s,instanceBase:i},"node instance raw proxy requested");const o=await x(`${i}${s}`,{method:r.method,headers:{...r.headers},body:es(r)}),a=Number(o.headers.get("content-length"));if(Number.isFinite(a)&&a>$.maxResponseBytes)return $.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${$.maxResponseBytes} bytes.`}});let c;try{c=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let r=0;const i=e.body.getReader();for(;;){const{done:e,value:s}=await i.read();if(e)break;if(r+=s.byteLength,r>t)throw await i.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,r)}(o,$.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return $.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${$.maxResponseBytes} bytes.`}})}return B({instanceId:n,action:"proxy.raw",method:r.method,path:s,statusCode:o.status,byteLength:c.length},"node instance raw proxy completed"),{data:{status:o.status,headers:Qi(o.headers),bodyBase64:c.toString("base64")}}}),L.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,t)=>{const n=t.params.id,r=t.params["*"]||"",i=t.url.indexOf("?"),s=i>=0?t.url.slice(i):"";let o;try{const i=gs(E.requireInstance(n)),a=new URL(`/${r}${s}`,`${i}/`);a.protocol="https:"===a.protocol?"wss:":"ws:";const c=function(e){const t=e["sec-websocket-protocol"],n=(Array.isArray(t)?t.join(","):"string"==typeof t?t:"").split(",").map(e=>e.trim()).filter(Boolean);return n.length?n:void 0}(t.headers);B({instanceId:n,action:"proxy.ws",path:`/${r}${s}`,upstreamUrl:a.toString(),protocols:c||[]},"node instance websocket proxy opening"),o=c?new l(a,c):new l(a),o.on("open",()=>{B({instanceId:n,action:"proxy.ws",path:`/${r}${s}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>o?.readyState===l.OPEN&&o.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>o?.close()),e.on("error",()=>o?.close())}),o.on("message",(t,n)=>{e.readyState===l.OPEN&&e.send(n?t:t.toString())}),o.on("close",()=>{B({instanceId:n,action:"proxy.ws",path:`/${r}${s}`},"node instance websocket proxy closed"),e.close()}),o.on("error",t=>{B({instanceId:n,action:"proxy.ws",path:`/${r}${s}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){B({instanceId:n,action:"proxy.ws",path:`/${r}${s}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),o?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}}),L}function Ps(e){const t=new URL("/api/node-agent/tunnel",e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}function Ms(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const r=t.secret?Pr({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},i=new l(n,{headers:r}),s=new Map,o=new Map;let a;const c=e=>{const n=e.startsWith("/")?e:`/${e}`,r="function"==typeof t.port?t.port():t.port,i=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${r}`);return i.protocol="ws:",i},d=e=>t.secret?Pr({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},u=(e,t=1e3,n="")=>{const r=s.get(e);s.delete(e),r?.upstream?.close(t,n),r?.tunnel?.close(t,n)},m=(e,t,n=!1)=>new Promise((r,i)=>{e.send(t,{binary:n},e=>e?i(e):r())});return i.on("open",()=>{i.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),a=e.nodeAgentEventForwarder?.addOutput(i)}),i.on("close",()=>{for(const e of s.keys())u(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of o)o.delete(e),t.controller.abort(),t.tunnel.close(1001,"Reverse tunnel disconnected.");a?.(),a=void 0}),i.on("message",async r=>{let a;try{a=JSON.parse(String(r))}catch{return void i.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const p=a&&"object"==typeof a?a:{};if("control-plane.http.open"===p.type){const e="string"==typeof p.streamId?p.streamId:"",r="string"==typeof p.route&&p.route.startsWith("/")?p.route:"/health",i=p.init&&"object"==typeof p.init?p.init:{},s=i.headers&&"object"==typeof i.headers?i.headers:{},a=new AbortController,c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(e),u=new l(c,{headers:d(c)});return o.set(e,{tunnel:u,controller:a}),u.on("open",async()=>{try{const n=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,r="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${r}`)})(r),{method:Lr(i.method),headers:{...s,...t.token?{authorization:`Bearer ${t.token}`}:{}},body:"string"==typeof i.body?i.body:void 0,signal:a.signal});if(await m(u,JSON.stringify({type:"node-agent.http.head",streamId:e,status:n.status,headers:Object.fromEntries(n.headers.entries())})),n.body){const e=n.body.getReader();for(;;){const{done:t,value:n}=await e.read();if(t)break;await m(u,Buffer.from(n),!0)}}await m(u,JSON.stringify({type:"node-agent.http.end",streamId:e})),u.close(1e3,"HTTP stream completed.")}catch(t){u.readyState===l.OPEN&&(await m(u,JSON.stringify({type:"node-agent.http.error",streamId:e,message:t instanceof Error?t.message:String(t)})).catch(()=>{}),u.close(1011,"HTTP stream failed."))}finally{o.delete(e)}}),u.on("close",()=>{a.abort(),o.delete(e)}),void u.on("error",()=>a.abort())}if("control-plane.websocket.open"===p.type){const e="string"==typeof p.streamId?p.streamId:"",r="string"==typeof p.route?p.route:"",o=Array.isArray(p.protocols)?p.protocols.filter(e=>"string"==typeof e):void 0;try{const a=t.token?{authorization:`Bearer ${t.token}`}:void 0,u=o?.length?new l(c(r),o,{headers:a}):new l(c(r),{headers:a}),m=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),p=new l(m,{headers:d(m)});s.set(e,{upstream:u,tunnel:p,close:(e=1e3,t="")=>{u.close(e,t),p.close(e,t)}}),u.on("open",()=>{i.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:u.protocol}))}),function(e,t,n={}){const r=n.pendingFrameLimit??256;let i=!1,s=cn(t);const o=[],a=[];let c;const d=()=>{c&&(clearTimeout(c),c=void 0)},l=(n,i)=>{if(n.length>=r)return dn(e,1011,"WebSocket bridge pending frame limit exceeded."),void dn(t,1011,"WebSocket bridge pending frame limit exceeded.");n.push(i)};n.upstreamOpenTimeoutMs&&!s&&(c=setTimeout(()=>{s||i||(dn(e,1011,"Upstream websocket did not open."),dn(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>un(e,a)),t.on("open",()=>{d(),s=!0,n.onUpstreamOpen?.(),un(t,o)}),e.on("message",(e,n=!1)=>{const r={data:e,isBinary:Boolean(n)};cn(t)?ln(t,r):l(o,r)}),t.on("message",(t,n=!1)=>{const r={data:t,isBinary:Boolean(n)};cn(e)?ln(e,r):l(a,r)}),t.on("close",(t,r)=>{d(),n.onUpstreamClose?.(t,r),(s||i||!n.onUpstreamCloseBeforeOpen?.())&&dn(e,t,r)}),t.on("error",t=>{n.onUpstreamError?.(t),(s||i||!n.onUpstreamErrorBeforeOpen?.(t))&&dn(e)}),e.on("close",(e,r)=>{d(),i=!0,n.onClientClose?.(e,r),dn(t,e,r)}),e.on("error",e=>{d(),i=!0,n.onClientError?.(e),dn(t,1011,"WebSocket bridge client failed.")})}(p,u,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{s.delete(e)},onClientError:t=>{s.delete(e),i.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{s.delete(e),i.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,code:"number"==typeof t?t:1e3,reason:Buffer.isBuffer(n)?n.toString("utf8"):String(n||"")}))},onUpstreamError:t=>{s.delete(e),i.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){i.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===p.type){const e="string"==typeof p.streamId?p.streamId:"";return void u(e,"number"==typeof p.code?p.code:1e3,"string"==typeof p.reason?p.reason:"")}if("control-plane.request"===p.type){const n="string"==typeof p.requestId?p.requestId:"",r=p.init&&"object"==typeof p.init?p.init:{},s="string"==typeof p.route&&p.route.startsWith("/")?p.route:"/health",o=r.headers&&"object"==typeof r.headers?r.headers:{};try{const a=await e.inject({method:Lr(r.method),url:`/api/node-agent${s}`,headers:{...o,...t.token?{authorization:`Bearer ${t.token}`}:{}},payload:"string"==typeof r.body?r.body:void 0});i.send(JSON.stringify({type:"node-agent.response",requestId:n,status:a.statusCode,headers:a.headers,body:a.body}))}catch(e){i.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)}}))}}}),i}async function Ls(e){const i=cr(e.dataDir),s=(o=e.host,a=e.port,Vt.parse({bindScope:"0.0.0.0"===o.trim()?"all-ipv4":"loopback",port:a}));var o,a;const c=t.existsSync(i.settingsPath),d=function(e,t){return new Ir(e.settingsPath,()=>({version:1,externalListener:t}),{schema:Ki,sanitize:cs})}(i,s),l=d.get().externalListener,u=function(e,r={}){return function(e,r={}){t.mkdirSync(n.dirname(e),{recursive:!0});const i={pid:process.pid,hostname:h.hostname(),component:r.component,command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:m.randomUUID(),dataDir:r.dataDir,host:r.host,port:r.port};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(br(e),`${JSON.stringify({token:i.token,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),vr(e,i),{lockPath:e,owner:i,release(){const n=Nr(e);n?.token===i.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(i){if("EEXIST"!==i.code)throw i;const s=Nr(e);if(zr(s?.pid))throw new yr(e,s,r.error);if(!s&&Tr(e)<2e3){if(n+1<5){_r();continue}throw new yr(e,void 0,r.error)}const o=m.randomUUID();if(!kr(e,o)){if(n+1<5){_r();continue}throw new yr(e,Nr(e),r.error)}const a=Nr(e);if(zr(a?.pid))throw Sr(wr(e)),new yr(e,a,r.error);if(s?.token&&a?.token!==s.token){Sr(wr(e));continue}if(!xr(e,o))continue;t.rmSync(e,{recursive:!0,force:!0})}const s=Nr(e);throw new yr(e,s,r.error)}(e,{...r,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(n.join(h.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`),{dataDir:i.dataDir,host:as(l.bindScope),port:l.port});try{const s={...e,port:l.port},o=await js(s),a=function(e,t,n,r){const i=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,s=new Mi(n),o=new Map,a=t=>{const n=t.url.replace(/\/$/,"");o.get(n)?.close(1e3,"Reverse tunnel reconnecting.");const s=Ms(e,{tunnelUrl:Ps(t.url),nodeId:r,port:()=>e.nodeAgentState.currentListenerPort,token:i,keyId:t.keyId,secret:t.secret});return o.set(n,s),s.on("close",()=>{o.get(n)===s&&o.delete(n)}),s};return{connect:a,connectConfigured:()=>{const n=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;if(t)return t;const n=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!n)return;const r=new URL("/api/node-agent/tunnel",n);return r.protocol="https:"===r.protocol?"wss:":"ws:",r.toString()}(t);if(n){const a=s.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID),c=(process.env.TASK_HANDOFF_CONTROL_PLANE_URL||n).replace(/\/$/,"");o.get(c)?.close(1e3,"Reverse tunnel reconnecting.");const d=Ms(e,{tunnelUrl:n,nodeId:r,port:()=>e.nodeAgentState.currentListenerPort,token:i,keyId:a?.keyId,secret:a?.secret});o.set(c,d)}for(const e of s.configuredRemoteControlPlanes())e.url&&!1!==e.active&&a({url:e.url,keyId:e.keyId,secret:e.secret})},closeAll:()=>{for(const e of o.values())e.close(1001,"Node agent shutting down.");o.clear()}}}(o,s,i,new Mi(i).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID));o.decorate("nodeAgentReverseTunnels",a);const m=new Cs({app:o,state:o.nodeAgentState,settings:d,config:l,source:c?"persisted":"bootstrap"});let p;o.decorate("nodeAgentListenerManager",m),function(e){let t=!1;const n=async n=>{if(!t){t=!0,a.closeAll(),p?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},r=()=>{n("SIGINT")},i=()=>{n("SIGTERM")};process.once("SIGINT",r),process.once("SIGTERM",i),e.addHook("onClose",async()=>{process.off("SIGINT",r),process.off("SIGTERM",i)})}(o),o.addHook("onClose",async()=>{p?.close(),u.release()});try{await o.ready();const s=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||Or(i.dataDir);p=await async function(e,i){!function(e,r=process.platform){if("win32"!==r){t.mkdirSync(n.dirname(e),{recursive:!0,mode:448});try{t.chmodSync(n.dirname(e),448)}catch{}try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}}(i);const s=r.createServer((t,n)=>{e.server.emit("request",t,n)});return s.on("upgrade",(t,n,r)=>{e.server.emit("upgrade",t,n,r)}),await new Promise((e,t)=>{s.once("error",t),s.listen(i,()=>{s.off("error",t),e()})}),s}(o,s),await m.start(),a.connectConfigured(),await(o.nodeAgentRestoreLocalInstances?.())}catch(e){throw await o.close(),e}}catch(e){throw u.release(),e}}function $s(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 Fs(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function Us(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 i=new e.Command;i.name("task-handoff-node-agent").description("Run a TaskHandoff node agent.").version(function(){try{return JSON.parse(t.readFileSync(n.resolve(__dirname,"..","package.json"),"utf8")).version||"unknown"}catch{return"unknown"}}()).option("--host <host>","Node agent host",process.env.TASK_HANDOFF_NODE_AGENT_HOST||"127.0.0.1").option("-p, --port <port>","Node agent port",$s,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",Fs).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 Ls({host:e.host,port:e.port,dataDir:e.dataDir,token:e.token,connectionMode:e.connectionMode,ipcPath:e.ipcPath,controlPlaneTunnelUrl:e.controlPlaneTunnelUrl})}),i.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",Us).option("--json","Print raw JSON output").action(async e=>{const t=i.opts(),n=e.ipcPath||t.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||t.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,o=e.endpoint?void 0:n||Or(s||ar()),c=await async function(e){const t={"content-type":"application/json",...e.token?{authorization:`Bearer ${e.token}`}:{}},n=JSON.stringify({...e.expiresInMs?{expiresInMs:e.expiresInMs}:{}}),i=e.endpoint?await fetch(`${e.endpoint.replace(/\/$/,"")}/api/node-agent/pairing/invites`,{method:"POST",headers:t,body:n}):await async function(e,t,n={}){const i=n.method||"GET",s="string"==typeof n.body||n.body instanceof Buffer?n.body:void 0===n.body||null===n.body?void 0:String(n.body),o=new Headers(n.headers||{});return void 0===s||o.has("content-length")||o.set("content-length",String(Buffer.byteLength(s))),new Promise((c,d)=>{const l=r.request({socketPath:e,method:i,path:`/api/node-agent${t}`,headers:Object.fromEntries(o.entries())},e=>{const t=e.statusCode||500;c(new Response("HEAD"!==i&&204!==t&&205!==t&&304!==t?a.Readable.toWeb(e):null,{status:t,headers:e.headers}))});l.on("error",d);const u=()=>l.destroy(new DOMException("The operation was aborted.","AbortError"));n.signal?.aborted?u():n.signal?.addEventListener("abort",u,{once:!0}),l.once("close",()=>n.signal?.removeEventListener("abort",u)),void 0!==s&&l.write(s),l.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error?.message||`Node agent pairing invite failed with HTTP ${i.status}`);const o="string"==typeof s.data?.joinToken?s.data.joinToken:"";if(!o)throw new Error("Node agent pairing invite response did not include a join token.");return{nodeId:"string"==typeof s.data?.nodeId?s.data.nodeId:"",joinToken:o,expiresAt:"string"==typeof s.data?.expiresAt?s.data.expiresAt:""}}({endpoint:e.endpoint,ipcPath:o,token:e.token,expiresInMs:e.expiresInMs});e.json?console.log(JSON.stringify(c,null,2)):(c.nodeId&&console.log(`Node: ${c.nodeId}`),console.log(`Join token: ${c.joinToken}`),c.expiresAt&&console.log(`Expires: ${c.expiresAt}`))}),await i.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:net"),s=require("node:url"),o=require("node:child_process"),a=require("node:stream"),c=require("fastify"),d=require("@fastify/websocket"),l=require("ws"),u=require("zod"),m=require("node:crypto"),p=require("node-pty"),g=require("node:os"),h=require("write-file-atomic"),f=require("semver"),I=require("node:fs/promises"),y=require("node:stream/promises"),A=require("tar"),b="undefined"!=typeof document?document.currentScript:null;const w=41943040,z="ai.sessions",N=u.z.string().trim().min(1).max(80),v=u.z.enum(["running","waiting","idle","failed"]);u.z.object({instanceId:u.z.string().trim().min(1).max(160),sessionId:u.z.string().trim().min(1).max(120),unread:u.z.boolean(),sessionUpdatedAt:u.z.string().datetime(),updatedAt:u.z.string().datetime()}).strict();const S=u.z.enum(["thinking","tool","editing","approval","responding","unknown"]),E=u.z.object({id:u.z.string().trim().min(1).max(240).optional(),kind:u.z.string().trim().min(1).max(80).optional(),name:u.z.string().trim().min(1).max(120),inputPreview:u.z.string().trim().max(500).optional(),startedAt:u.z.string().datetime().optional()}).strict(),_=u.z.enum(["pending-init","running","interrupted","completed","errored","shutdown","not-found"]),T=u.z.enum(["started","interacted","interrupted"]),k=u.z.object({threadId:u.z.string().trim().min(1).max(240),path:u.z.string().trim().max(4096).optional(),status:_,activity:T.optional(),message:u.z.string().trim().max(1e3).optional(),updatedAt:u.z.string().datetime()}).strict(),x=u.z.object({toolCalls:u.z.number().int().min(0).default(0),edits:u.z.number().int().min(0).default(0),approvals:u.z.number().int().min(0).default(0)}).strict().default({toolCalls:0,edits:0,approvals:0}),C=u.z.object({send:u.z.boolean().optional(),interrupt:u.z.boolean().optional(),approval:u.z.boolean().optional()}).strict(),O=u.z.enum(["image","file"]),R=u.z.object({id:u.z.string().trim().min(1).max(120),kind:O,name:u.z.string().trim().min(1).max(240),mime:u.z.string().trim().min(1).max(120),size:u.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)}),D=u.z.union([R.extend({source:u.z.object({type:u.z.literal("inline"),encoding:u.z.literal("base64"),data:u.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:u.z.ZodIssueCode.custom,path:["size"],message:`Inline ${e.kind} must be between 1 byte and ${n} bytes.`})}),R.extend({source:u.z.object({type:u.z.literal("runtime-path"),path:u.z.string().trim().min(1).max(4096)}).strict()}).strict()]),j=R.extend({sourceType:u.z.enum(["inline","runtime-path"])}).strict(),P=u.z.union([u.z.object({id:u.z.string().trim().min(1).max(120),kind:O.optional(),source:u.z.object({type:u.z.literal("upload-ref")}).strict().default({type:"upload-ref"})}).strict(),u.z.object({id:u.z.string().trim().min(1).max(120),kind:O,name:u.z.string().trim().min(1).max(240),mime:u.z.string().trim().min(1).max(120),size:u.z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),source:u.z.object({type:u.z.literal("runtime-path"),path:u.z.string().trim().min(1).max(4096)}).strict()}).strict()]),M=u.z.enum(["auto","queue","steer","immediate"]),L=u.z.enum(["ask","auto-review","full-access"]),$=u.z.enum(["review","rename","goal","compact"]);u.z.object({command:$,argument:u.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.`})}),u.z.object({command:$,value:u.z.string().max(4e3).optional(),turnId:u.z.string().trim().min(1).max(240).optional()}).strict(),u.z.enum(["skill","app","plugin"]);const F=u.z.object({name:u.z.string().trim().min(1).max(240),path:u.z.string().trim().min(1).max(4096)}),U=u.z.discriminatedUnion("kind",[F.extend({kind:u.z.literal("skill"),path:u.z.string().trim().min(1).max(4096).refine(e=>e.startsWith("/"),"Skill paths must be absolute.")}).strict(),F.extend({kind:u.z.literal("app"),path:u.z.string().trim().min(7).max(4096).regex(/^app:\/\/[^\s/]+$/,"App paths must use app://<id>.")}).strict(),F.extend({kind:u.z.literal("plugin"),path:u.z.string().trim().min(10).max(4096).regex(/^plugin:\/\/[^\s/]+$/,"Plugin paths must use plugin://<id>.")}).strict()]),V=u.z.array(U).max(20).default([]),H=u.z.enum(["plugin","skill","file","directory","app"]),q=u.z.object({kind:H,name:u.z.string().trim().min(1).max(240),description:u.z.string().trim().max(1e3).optional(),path:u.z.string().trim().min(1).max(4096),icon:u.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."})}),B=u.z.object({category:u.z.enum(["skills","plugins","apps","files"]),code:u.z.string().trim().min(1).max(160),message:u.z.string().trim().min(1).max(2e3)}).strict();u.z.object({sessionId:u.z.string().trim().min(1).max(120),providerSessionId:u.z.string().trim().min(1).max(240),cwd:u.z.string().trim().min(1).max(4096),candidates:u.z.array(q).max(1e3).default([]),diagnostics:u.z.array(B).max(20).default([])}).strict(),u.z.object({query:u.z.string().trim().max(240).default("")}).strict(),u.z.object({sessionId:u.z.string().trim().min(1).max(120),cwd:u.z.string().trim().min(1).max(4096),query:u.z.string().trim().max(240),requestId:u.z.string().trim().min(1).max(160),candidates:u.z.array(q.refine(e=>"file"===e.kind||"directory"===e.kind,"File search only returns files and directories.")).max(200).default([]),complete:u.z.boolean().default(!1)}).strict();const K=u.z.object({message:u.z.string().trim().min(1).max(2e4),mode:M.optional(),permissionMode:L.optional()});K.extend({attachments:u.z.array(D).max(6).default([]),references:V}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>w&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),K.extend({attachments:u.z.array(P).max(6).default([]),references:V}).strict(),u.z.object({decision:u.z.enum(["allow","deny","skip"])}).strict(),u.z.object({queueIds:u.z.array(u.z.string().trim().min(1).max(120)).max(100)}).strict(),u.z.object({code:u.z.string().trim().min(1).max(160),message:u.z.string(),instanceId:u.z.string().trim().min(1).max(160).optional(),nodeId:u.z.string().trim().min(1).max(160).optional(),route:u.z.string().trim().min(1).max(4096).optional()}).strict();const G=u.z.object({id:u.z.string().trim().min(1).max(120),message:u.z.string().trim().min(1).max(2e4),attachments:u.z.array(j).max(6).default([]),references:V,permissionMode:L.optional(),status:u.z.enum(["queued","sending","failed"]).default("queued"),createdAt:u.z.string().datetime(),updatedAt:u.z.string().datetime(),error:u.z.string().trim().max(4e3).optional()}).strict(),J=u.z.object({pendingCount:u.z.number().int().min(0).default(0),items:u.z.array(G).max(100).default([])}).strict().default({pendingCount:0,items:[]}),W=u.z.enum(["control","realtime","adapter-snapshot","transcript-tail","transcript-scan","process-scan","app-session"]),Y=u.z.object({id:u.z.string().trim().min(1).max(240),status:u.z.enum(["running","completed"]),startedAt:u.z.string().datetime().optional(),completedAt:u.z.string().datetime().optional()}).strict(),X=u.z.object({id:u.z.string().trim().min(1).max(240),providerTurnId:u.z.string().trim().max(240).optional(),source:W.optional(),userPrompt:u.z.string().trim().optional(),status:u.z.enum(["queued","running","waiting","completed","failed"]).default("running"),phase:S.optional(),summary:u.z.string().trim().max(1e3).optional(),lastMessage:u.z.string().trim().optional(),lastMessageItemId:u.z.string().trim().max(240).optional(),contextCompactions:u.z.array(Y).max(20).optional(),revision:u.z.number().int().min(0).default(0),sourcePriority:u.z.number().int().min(0).max(100).optional(),snapshotVersion:u.z.number().int().min(0).optional(),observedAt:u.z.string().datetime().optional(),startedAt:u.z.string().datetime().optional(),updatedAt:u.z.string().datetime().optional(),completedAt:u.z.string().datetime().optional()}).strict(),Z=X.pick({id:!0,providerTurnId:!0,userPrompt:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,contextCompactions:!0,startedAt:!0,updatedAt:!0,completedAt:!0}).strict(),Q=u.z.object({id:u.z.string().trim().min(1).max(120),agent:N,appSessionId:u.z.string().trim().max(120).optional(),appId:u.z.string().trim().max(120).optional(),providerSessionId:u.z.string().trim().max(240).optional(),providerMeta:u.z.record(u.z.string(),u.z.unknown()).optional(),appBindingKeys:u.z.array(u.z.string().trim().min(1).max(240)).max(20).optional(),actions:C.optional(),activeTurnId:u.z.string().trim().max(240).optional(),title:u.z.string().trim().max(240).optional(),cwd:u.z.string().trim().max(4096).optional(),userPrompt:u.z.string().trim().optional(),turns:u.z.array(X).max(50).optional(),status:v.default("running"),phase:S.default("unknown"),summary:u.z.string().trim().max(1e3).optional(),lastMessage:u.z.string().trim().optional(),lastMessageItemId:u.z.string().trim().max(240).optional(),currentTool:E.optional(),toolCallsSinceLastMessage:u.z.number().int().min(0).default(0),subAgents:u.z.array(k).max(50).default([]),transcriptPath:u.z.string().trim().max(4096).optional(),transcriptSize:u.z.number().int().min(0).optional(),startedAt:u.z.string().datetime(),updatedAt:u.z.string().datetime(),completedAt:u.z.string().datetime().optional(),error:u.z.string().trim().max(4e3).optional(),counters:x,queue:J}).strict();u.z.object({session:Q,provider:u.z.string().trim().min(1).max(80),action:u.z.enum(["send","queue","steer","interrupt","approval"]),decision:u.z.enum(["allow","deny","skip"]).optional(),turnId:u.z.string().trim().min(1).max(240).optional(),providerTurnId:u.z.string().trim().min(1).max(240).optional(),queueId:u.z.string().trim().min(1).max(120).optional()}).strict();const ee=u.z.object({id:u.z.string().trim().min(1).max(120),agent:u.z.enum(["codex","claude"]),providerSessionId:u.z.string().trim().min(1).max(240),title:u.z.string().trim().max(240).optional(),userPrompt:u.z.string().trim().optional(),lastMessage:u.z.string().trim().optional(),cwd:u.z.string().trim().min(1).max(4096),lastActiveAt:u.z.string().datetime(),archivedAt:u.z.string().datetime()}).strict();u.z.object({schemaVersion:u.z.literal(1).default(1),items:u.z.array(ee).max(50).default([])}).strict(),u.z.object({items:u.z.array(ee).max(50).default([])}).strict(),u.z.object({item:ee,turns:u.z.array(Z).max(50).default([])}).strict(),u.z.object({disposition:u.z.enum(["resumed","already-open"]),aiSessionId:u.z.string().trim().min(1).max(120),providerSessionId:u.z.string().trim().min(1).max(240),appSessionId:u.z.string().trim().min(1).max(120)}).strict();const te=Q.pick({id:!0,agent:!0,appSessionId:!0,appId:!0,providerSessionId:!0,providerMeta:!0,appBindingKeys:!0,actions:!0,activeTurnId:!0,title:!0,cwd:!0,userPrompt:!0,turns:!0,status:!0,phase:!0,summary:!0,lastMessage:!0,lastMessageItemId:!0,currentTool:!0,toolCallsSinceLastMessage:!0,subAgents:!0,queue:!0,startedAt:!0,updatedAt:!0,error:!0}),ne=u.z.object({runningCount:u.z.number().int().min(0).default(0),waitingCount:u.z.number().int().min(0).default(0),staleCount:u.z.number().int().min(0).default(0),sessions:u.z.array(te).default([]),updatedAt:u.z.string().datetime()}).strict();u.z.object({streamId:u.z.string().trim().min(1).max(240),revision:u.z.number().int().min(0),lastEventAt:u.z.string().datetime(),snapshot:ne}).strict(),ne.pick({runningCount:!0,waitingCount:!0,staleCount:!0,updatedAt:!0}).extend({idleCount:u.z.number().int().min(0).default(0),problemCount:u.z.number().int().min(0).default(0),revision:u.z.number().int().min(0).optional()});const ie=u.z.enum(["provider-event","app-session-created","app-session-updated","app-session-deleted","discovery-scan","control-action","heartbeat-sync","startup"]),re=u.z.object({streamId:u.z.string().trim().min(1).max(240),instanceId:u.z.string().trim().min(1).max(160),nodeId:u.z.string().trim().min(1).max(160).optional(),revision:u.z.number().int().min(0),previousRevision:u.z.number().int().min(0).optional(),traceId:u.z.string().trim().min(1).max(160),generatedAt:u.z.string().datetime(),reason:ie}).strict(),se=u.z.object({meta:re,snapshot:ne}).strict(),oe=u.z.object({meta:re,upserted:u.z.array(te).default([]),removed:u.z.array(u.z.string().trim().min(1).max(120)).default([])}).strict(),ae=u.z.object({meta:re,sessionIds:u.z.array(u.z.string().trim().min(1).max(120)).default([]),expiresAt:u.z.string().datetime()}).strict();u.z.object({instanceId:u.z.string().trim().min(1).max(160),nodeId:u.z.string().trim().min(1).max(160).optional(),sessionId:u.z.string().trim().min(1).max(120),providerSessionId:u.z.string().trim().min(1).max(240),turnId:u.z.string().trim().min(1).max(240),itemId:u.z.string().trim().min(1).max(240),delta:u.z.string().min(1),generatedAt:u.z.string().datetime()}).strict(),u.z.object({streamId:u.z.string().trim().min(1).max(240),instanceId:u.z.string().trim().min(1).max(160),sinceRevision:u.z.number().int().min(0),latestRevision:u.z.number().int().min(0),earliestRetainedRevision:u.z.number().int().min(0),syncRequired:u.z.boolean().default(!1),events:u.z.array(u.z.discriminatedUnion("type",[u.z.object({type:u.z.literal("ai-session.snapshot"),payload:se}).strict(),u.z.object({type:u.z.literal("ai-session.patch"),payload:oe}).strict(),u.z.object({type:u.z.literal("ai-session.removed"),payload:ae}).strict()])).default([])}).strict();const ce=u.z.object({source:W,sourcePriority:u.z.number().int().min(0).max(100).optional(),observedAt:u.z.string().datetime().optional(),snapshotVersion:u.z.number().int().min(0).optional()}).strict(),de=ce.extend({type:u.z.literal("snapshot"),agent:u.z.string().trim().min(1).max(80),appSessionId:u.z.string().trim().max(120).optional(),appId:u.z.string().trim().max(120).optional(),providerSessionId:u.z.string().trim().max(240).optional(),providerMeta:u.z.record(u.z.string(),u.z.unknown()).optional(),appBindingKeys:u.z.array(u.z.string().trim().min(1).max(240)).max(20).optional(),actions:C.optional(),title:u.z.string().trim().max(240).optional(),cwd:u.z.string().trim().max(4096).optional(),activeTurnId:u.z.string().trim().max(240).optional(),userPrompt:u.z.string().trim().optional(),turns:u.z.array(X).max(50).optional(),status:v.optional(),phase:S.optional(),summary:u.z.string().trim().max(1e3).optional(),lastMessage:u.z.string().trim().optional(),lastMessageItemId:u.z.string().trim().max(240).optional(),currentTool:E.optional(),toolCallsSinceLastMessage:u.z.number().int().min(0).optional(),subAgents:u.z.array(k).max(50).optional(),transcriptPath:u.z.string().trim().max(4096).optional(),transcriptSize:u.z.number().int().min(0).optional(),replaceActivity:u.z.boolean().optional()}).strict(),le=ce.extend({type:u.z.literal("event"),sessionId:u.z.string().trim().min(1).max(120),kind:u.z.enum(["lifecycle","send-ack","turn-started","user-message","assistant-message","approval-requested","turn-completed","tool-activity","sub-agent-activity","context-compaction"]),activeTurnId:u.z.string().trim().max(240).optional(),providerTurnId:u.z.string().trim().max(240).optional(),userPrompt:u.z.string().trim().optional(),text:u.z.string().optional(),itemId:u.z.string().trim().max(240).optional(),status:v.optional(),phase:S.optional(),summary:u.z.string().trim().max(1e3).optional(),error:u.z.string().trim().max(4e3).optional(),currentTool:E.nullable().optional(),toolCallsSinceLastMessage:u.z.number().int().min(0).optional(),subAgents:u.z.array(k).max(50).optional(),contextCompaction:Y.optional(),counters:u.z.object({toolCalls:u.z.number().int().min(0).optional(),edits:u.z.number().int().min(0).optional(),approvals:u.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"})});u.z.discriminatedUnion("type",[de,le]);const ue=u.z.union([u.z.object({type:u.z.literal("schedule"),scheduleKind:u.z.literal("interval").default("interval"),intervalMs:u.z.number().int().min(1e3)}).strict(),u.z.object({type:u.z.literal("schedule"),scheduleKind:u.z.literal("daily"),timeOfDay:u.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:u.z.string().trim().min(1).max(120)}).strict(),u.z.object({type:u.z.literal("schedule"),scheduleKind:u.z.literal("weekly"),weekdays:u.z.array(u.z.number().int().min(0).max(6)).min(1).max(7),timeOfDay:u.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),timezone:u.z.string().trim().min(1).max(120)}).strict()]),me=u.z.union([ue,u.z.object({type:u.z.literal("file-change"),roots:u.z.array(u.z.string().trim().min(1).max(4096)).min(1).max(50),globs:u.z.array(u.z.string().trim().min(1).max(500)).min(1).max(100),ignore:u.z.array(u.z.string().trim().min(1).max(500)).max(100).optional(),debounceMs:u.z.number().int().min(100).max(6e4).default(1500)}).strict(),u.z.object({type:u.z.literal("ai-session"),agent:u.z.string().trim().min(1).max(80).optional(),statuses:u.z.array(u.z.enum(["running","waiting","idle","failed"])).max(20).optional(),phases:u.z.array(u.z.enum(["thinking","tool","editing","approval","responding","unknown"])).max(20).optional()}).strict()]),pe=u.z.object({promptTemplate:u.z.string().trim().min(1).max(2e4)}).strict(),ge=u.z.object({cooldownMs:u.z.number().int().min(0).max(864e5).optional(),maxConcurrentRuns:u.z.number().int().min(1).max(20).default(1),whenBusy:u.z.enum(["skip","queue"]).default("skip")}).strict(),he=u.z.object({configHash:u.z.string().trim().min(8).max(80),name:u.z.string().trim().min(1).max(160),description:u.z.string().trim().max(1e3).optional(),source:me,action:pe,policy:ge.default({maxConcurrentRuns:1,whenBusy:"skip"}),createdAt:u.z.string().datetime(),updatedAt:u.z.string().datetime()}).strict(),fe=u.z.object({type:u.z.literal("ai-session"),aiSessionId:u.z.string().trim().min(1).max(160)}).strict(),Ie=u.z.object({configHash:u.z.string().trim().min(8).max(80),deploymentId:u.z.string().trim().min(1).max(240).optional(),instanceId:u.z.string().trim().min(1).max(160),origin:u.z.enum(["control-plane","controlled-instance"]).default("controlled-instance"),enabled:u.z.boolean().default(!0),target:fe,localName:u.z.string().trim().min(1).max(160).optional(),createdAt:u.z.string().datetime(),updatedAt:u.z.string().datetime()}).strict(),ye=u.z.object({configHash:u.z.string().trim().min(8).max(80),deploymentId:u.z.string().trim().min(1).max(240).optional(),instanceId:u.z.string().trim().min(1).max(160),status:u.z.enum(["idle","running","disabled","error"]).default("idle"),lastTriggeredAt:u.z.string().datetime().optional(),lastCompletedAt:u.z.string().datetime().optional(),lastSkippedAt:u.z.string().datetime().optional(),lastError:u.z.string().trim().max(4e3).optional(),runCount:u.z.number().int().min(0).default(0),skippedCount:u.z.number().int().min(0).default(0)}).strict(),Ae=u.z.object({id:u.z.string().trim().min(1).max(160),configHash:u.z.string().trim().min(8).max(80),deploymentId:u.z.string().trim().min(1).max(240).optional(),instanceId:u.z.string().trim().min(1).max(160),eventType:u.z.enum(["manual","schedule","file-change","ai-session"]),status:u.z.enum(["started","completed","failed","skipped"]),target:fe,promptPreview:u.z.string().trim().max(500),eventSummary:u.z.string().trim().max(1e3).optional(),error:u.z.string().trim().max(4e3).optional(),startedAt:u.z.string().datetime(),completedAt:u.z.string().datetime().optional()}).strict();u.z.object({schemaVersion:u.z.literal(1).default(1),configs:u.z.array(he).default([]),deployments:u.z.array(Ie).default([]),runtime:u.z.array(ye).default([]),recentRuns:u.z.array(Ae).default([])}).strict();const be="2026-07-28",we=u.z.string(),ze=u.z.string().trim().min(1).max(120).regex(/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/),Ne=u.z.string().datetime(),ve=u.z.record(u.z.string(),u.z.string()).default({}),Se=u.z.record(u.z.string(),u.z.string()).default({}),Ee=u.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Protocol version must use YYYY-MM-DD format."),_e=/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/,Te=/^sha256:([a-fA-F0-9]{64})$/,ke=/^(?:localhost|[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?)(?::[1-9][0-9]{0,4})?$/,xe=/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*$/;function Ce(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?Te.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&&!_e.test(d))throw new Error("Docker image tag is invalid.");if(!d&&!s)throw new Error("Docker image reference must include an explicit tag or sha256 digest.");const u=l.split("/");if(!u.length||u.some(e=>!e))throw new Error("Docker image repository path is invalid.");const m=u.length>1&&(u[0].includes(".")||u[0].includes(":")||"localhost"===u[0]),p=m?u.slice(1):u;if(m&&!ke.test(u[0].toLowerCase()))throw new Error("Docker image registry host or port is invalid.");if(!p.length||p.some(e=>!xe.test(e)))throw new Error("Docker image repository names must be lowercase and use valid separators.");const g=u.map((e,t)=>m&&0===t?e.toLowerCase():e).join("/"),h=s?`sha256:${s[1].toLowerCase()}`:void 0;return`${g}${d?`:${d}`:""}${h?`@${h}`:""}`}function Oe(e){const t=Ce(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 Re=u.z.string().trim().min(1).max(512).transform((e,t)=>{try{return Ce(e)}catch(e){return t.addIssue({code:"custom",message:e instanceof Error?e.message:String(e)}),u.z.NEVER}}),De=u.z.string().trim().transform((e,t)=>{const n=Te.exec(e);return n?`sha256:${n[1].toLowerCase()}`:(t.addIssue({code:"custom",message:"Docker image digest must use sha256 followed by 64 hexadecimal characters."}),u.z.NEVER)}),je=u.z.object({codexModelHash:ze.nullable().optional(),claudeModelHash:ze.nullable().optional()}).strict().default({}),Pe=u.z.object({imageId:ze,tag:u.z.string().trim().min(1).max(128).regex(_e).optional()}).strict(),Me={img_default:"market_taskhandoff_browser",img_codex:"market_taskhandoff_codex",img_ai:"market_taskhandoff_ai"};function Le(e,t){if(e&&"object"==typeof e&&!Array.isArray(e)){const t=e;return{imageId:"string"==typeof t.imageId&&Me[t.imageId]||t.imageId,..."string"==typeof t.tag?{tag:t.tag}:{}}}if("string"==typeof t)return{imageId:Me[t]||t}}function $e(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,{defaultImageId:n,...i}=t;return{...i,defaultImageSelection:Le(t.defaultImageSelection,n)}}const Fe=u.z.object({id:ze,name:u.z.string().trim().min(1).max(120),kind:u.z.enum(["tty","gui","web"]),source:u.z.enum(["builtin","custom"]),availability:u.z.enum(["available","missing-dependency"]),capabilities:u.z.object({automation:u.z.enum(["cdp"]).optional(),supportsCwdSelection:u.z.boolean().default(!1)}).strict().default({supportsCwdSelection:!1}),diagnosticCode:u.z.enum(["APP_EXECUTABLE_NOT_FOUND"]).optional()}).strict(),Ue=u.z.object({code:u.z.enum(["APP_CATALOG_INVALID"]),message:u.z.string().trim().min(1).max(500)}).strict(),Ve=u.z.object({items:u.z.array(Fe).max(256),observedAt:Ne,issues:u.z.array(Ue).max(32).default([])}).strict(),He=u.z.enum(["linux","darwin","win32","freebsd","openbsd","aix","sunos","unknown"]),qe=u.z.enum(["x64","arm64","arm","ia32","ppc64","s390x","riscv64","unknown"]),Be=u.z.enum(["apt","dnf","brew","npm"]),Ke=u.z.enum(["user","passwordless-sudo","root"]),Ge=u.z.object({platform:He,arch:qe,installers:u.z.array(Be).max(8),privilege:Ke,installerAccess:u.z.object({npmGlobalWritable:u.z.boolean().optional()}).strict().optional()}).strict(),Je=u.z.enum(["installed","not-installed","broken","unsupported"]),We=u.z.enum(["recipe","bundled","external","none"]),Ye=u.z.object({code:u.z.enum(["BUNDLED","EXTERNALLY_MANAGED","ALREADY_INSTALLED","NOT_INSTALLED","UNSUPPORTED_PLATFORM","INSTALLER_UNAVAILABLE","INSTALLER_NOT_WRITABLE","INSUFFICIENT_PRIVILEGE","OPERATION_IN_PROGRESS"]),message:u.z.string().trim().min(1).max(500)}).strict(),Xe=u.z.object({id:ze,name:u.z.string().trim().min(1).max(120),kind:u.z.enum(["tty","gui","web"]),description:u.z.string().trim().max(500).optional(),state:Je,managementSource:We,version:u.z.string().trim().max(120).optional(),canInstall:u.z.boolean(),canUninstall:u.z.boolean(),installReason:Ye.optional(),uninstallReason:Ye.optional(),activeJobId:ze.optional()}).strict(),Ze=u.z.enum(["install","uninstall"]),Qe=u.z.enum(["queued","running","succeeded","failed","cancelled","interrupted"]),et=u.z.object({current:u.z.number().finite().nonnegative().optional(),total:u.z.number().finite().positive().optional(),unit:u.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"]}),tt=u.z.object({executable:u.z.string().trim().min(1).max(4096),args:u.z.array(u.z.string().max(4096)).max(128)}).strict(),nt=u.z.object({code:u.z.string().trim().min(1).max(120).regex(/^[a-z0-9][a-z0-9._-]*$/),message:u.z.string().trim().min(1).max(4096),retryable:u.z.boolean(),sessionIds:u.z.array(ze).max(64).optional()}).strict(),it=u.z.object({id:ze,requestId:ze.optional(),appId:ze,operation:Ze,state:Qe,phase:u.z.string().trim().min(1).max(120).optional(),progress:et.optional(),command:tt.optional(),logTail:u.z.string().max(32768).optional(),logTruncated:u.z.boolean().optional(),error:nt.optional(),requestedAt:Ne,startedAt:Ne.optional(),finishedAt:Ne.optional(),updatedAt:Ne}).strict(),rt=u.z.object({streamId:ze,sequence:u.z.number().int().nonnegative(),capabilities:Ge,apps:u.z.array(Xe).max(256),activeJobs:u.z.array(it).max(256),recentJobs:u.z.array(it).max(256),observedAt:Ne}).strict();u.z.object({requestId:ze.optional()}).strict(),u.z.object({job:it}).strict(),u.z.object({type:u.z.literal("app-management"),streamId:ze,sequence:u.z.number().int().nonnegative(),observedAt:Ne,job:it.optional(),snapshot:rt.optional()}).strict().refine(e=>void 0!==e.job||void 0!==e.snapshot,{message:"An app management event requires a job or snapshot."});const st=u.z.object({component:u.z.enum(["control-plane","node-agent","controlled-instance"]),packageName:u.z.string().trim().max(160).optional(),packageVersion:u.z.string().trim().max(80).optional(),protocolVersion:we.optional(),buildId:u.z.string().trim().max(160).optional(),builtAt:u.z.string().trim().max(120).optional(),gitCommit:u.z.string().trim().max(120).optional(),imageRef:u.z.string().trim().max(512).optional(),imageDigest:u.z.string().trim().max(240).optional()}).strict(),ot=u.z.enum(["stable","beta","alpha"]),at=u.z.object({packageName:u.z.literal("@task-handoff/controlled-instance"),version:u.z.string().trim().min(1).max(80),platform:u.z.string().trim().min(1).max(40),arch:u.z.string().trim().min(1).max(40),formatVersion:u.z.number().int().positive(),launcherAbi:u.z.number().int().positive(),entrypoint:u.z.string().trim().min(1).max(512),sha256:u.z.string().regex(/^[a-f0-9]{64}$/)}).strict(),ct=u.z.object({code:u.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:u.z.string().trim().min(1).max(4096),expectedVersion:u.z.string().trim().min(1).max(80).optional(),actualVersion:u.z.string().trim().min(1).max(80).optional(),retryable:u.z.boolean().default(!1)}).strict(),dt=u.z.object({desiredVersion:u.z.string().trim().min(1).max(80),actualVersion:u.z.string().trim().min(1).max(80).optional(),phase:u.z.enum(["pending","draining","installing","restarting","verifying","matched","failed"]),attempt:u.z.number().int().nonnegative().default(0),lastAttemptAt:Ne.optional(),matchedAt:Ne.optional(),error:ct.optional()}).strict(),lt=u.z.object({runningInstanceCount:u.z.number().int().nonnegative(),stoppedInstanceCount:u.z.number().int().nonnegative(),activeInstanceCount:u.z.number().int().nonnegative(),restartInstanceCount:u.z.number().int().nonnegative(),runningInstanceIds:u.z.array(ze).max(1024).default([]),stoppedInstanceIds:u.z.array(ze).max(1024).default([]),activeInstanceIds:u.z.array(ze).max(1024).default([])}).strict(),ut=u.z.object({phase:u.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),desiredVersion:u.z.string().trim().min(1).max(80),nodeVersion:u.z.string().trim().min(1).max(80).optional(),expectedInstanceIds:u.z.array(ze).max(1024).default([]),expectedInstanceCount:u.z.number().int().nonnegative(),matchedInstanceCount:u.z.number().int().nonnegative(),pendingInstanceCount:u.z.number().int().nonnegative(),failedInstanceCount:u.z.number().int().nonnegative(),deferredInstanceCount:u.z.number().int().nonnegative().default(0)}).strict(),mt=u.z.object({channel:ot.default("stable")}).strict(),pt=u.z.object({source:u.z.literal("npm"),channel:ot,currentVersion:u.z.string().trim().max(240).optional(),availableVersion:u.z.string().trim().min(1).max(240),artifactRef:u.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:u.z.array(at).default([]),impact:lt,updateAvailable:u.z.boolean(),supported:u.z.boolean().default(!0),reason:u.z.string().trim().max(2048).optional(),checkedAt:Ne,preflightToken:u.z.string().trim().min(16).max(240).optional()}).strict(),gt=u.z.object({id:ze,nodeId:ze,source:u.z.literal("npm"),channel:ot,fromVersion:u.z.string().trim().max(240).optional(),toVersion:u.z.string().trim().min(1).max(240),artifactRef:u.z.string().trim().min(1).max(512).optional(),runtimeArtifacts:u.z.array(at).default([]),impact:lt,rollout:ut,status:u.z.enum(["queued","updating-node","restarting-node","converging-instances","succeeded","degraded","failed"]),error:ct.optional(),startedAt:Ne.optional(),completedAt:Ne.optional(),createdAt:Ne,updatedAt:Ne}).strict(),ht=u.z.object({channel:ot,targetVersion:u.z.string().trim().min(1).max(240),preflightToken:u.z.string().trim().min(16).max(240)}).strict(),ft=u.z.object({type:u.z.enum(["branch","tag","commit"]),name:u.z.string().trim().min(1).max(240).optional(),commit:u.z.string().trim().max(80).optional()}).strict(),It=u.z.object({type:u.z.enum(["none","ssh-key","https-token"]).default("none"),secretId:u.z.string().trim().min(1).max(120).optional()}).strict(),yt=u.z.object({depth:u.z.number().int().positive().max(1e5).optional(),submodules:u.z.boolean().default(!1),lfs:u.z.boolean().default(!1),subdirectory:u.z.string().trim().max(240).default("")}).strict();u.z.object({id:ze,name:u.z.string().trim().min(1).max(160),url:u.z.string().trim().min(1).max(2048),provider:u.z.string().trim().max(80).optional(),ref:ft.default({type:"branch",name:"main"}),auth:It.default({type:"none"}),clone:yt.default({submodules:!1,lfs:!1,subdirectory:""}),defaultImageSelection:Pe.optional(),labels:ve,createdAt:Ne,updatedAt:Ne}).strict();const At=u.z.object({id:ze,nodeId:ze,name:u.z.string().trim().min(1).max(160),path:u.z.string().trim().min(1).max(4096),defaultImageSelection:Pe.optional(),labels:ve,createdAt:Ne,updatedAt:Ne}).strict(),bt=u.z.discriminatedUnion("type",[u.z.object({type:u.z.literal("git-repository"),repositoryId:ze.optional(),url:u.z.string().trim().min(1).max(2048),provider:u.z.string().trim().max(80).optional(),ref:ft.default({type:"branch",name:"main"}),auth:It.default({type:"none"}),clone:yt.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),u.z.object({type:u.z.literal("git-template"),url:u.z.string().trim().min(1).max(2048),templateId:u.z.string().trim().min(1).max(120).optional(),ref:ft.default({type:"branch",name:"main"}),auth:It.default({type:"none"}),clone:yt.default({submodules:!1,lfs:!1,subdirectory:""})}).strict(),u.z.object({type:u.z.literal("local-folder"),localFolderId:ze.optional(),path:u.z.string().trim().min(1).max(4096),ownerNodeId:ze.optional()}).strict()]),wt=u.z.object({mode:u.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]),path:u.z.string().trim().min(1).max(4096).default("/workspace"),volumeName:u.z.string().trim().max(240).optional(),readOnly:u.z.boolean().default(!1)}).strict(),zt=u.z.enum(["codex","claude"]),Nt=u.z.object({id:ze,name:u.z.string().trim().min(1).max(160),source:bt,defaultImageSelection:Pe.optional(),defaultNodeId:ze.optional(),defaultRuntimeId:ze.optional(),workspacePolicy:wt,labels:ve,createdAt:Ne,updatedAt:Ne}).strict(),vt=u.z.object({id:ze,name:u.z.string().trim().min(1).max(160),endpoint:u.z.string().trim().min(1).max(2048),key:u.z.string().trim().min(1).max(4096),model:u.z.string().trim().min(1).max(240),app:zt,enabled:u.z.boolean().default(!0),order:u.z.number().int().min(0).max(1e6).default(0),labels:ve,createdAt:Ne,updatedAt:Ne}).strict(),St=vt,Et=vt.omit({key:!0}).extend({keyPreview:u.z.string().trim().min(1).max(160),keySet:u.z.boolean()}).strict(),_t=Et.extend({referenceCount:u.z.number().int().min(0)}).strict(),Tt=u.z.object({instanceId:ze,codexModelHash:ze.optional(),claudeModelHash:ze.optional(),updatedAt:Ne}).strict(),kt=u.z.discriminatedUnion("type",[u.z.object({type:u.z.literal("control-plane"),name:vt.shape.name,enabled:vt.shape.enabled,order:vt.shape.order}).strict(),u.z.object({type:u.z.literal("node"),nodeId:ze,name:vt.shape.name,enabled:vt.shape.enabled,order:vt.shape.order,referenceCount:u.z.number().int().min(0)}).strict()]),xt=u.z.object({id:ze,model:Et,locations:u.z.array(kt).min(1),referenceCount:u.z.number().int().min(0).default(0)}).strict(),Ct=u.z.object({nodeId:ze,code:u.z.string().trim().min(1).max(120),message:u.z.string().trim().min(1).max(2e3)}).strict();u.z.object({models:u.z.array(xt),nodeDiagnostics:u.z.array(Ct).default([]),updatedAt:Ne}).strict();const Ot=vt.omit({id:!0,createdAt:!0,updatedAt:!0}).strict(),Rt=Ot.partial().strict(),Dt=vt,jt=u.z.object({modelSelection:je,codexModelHash:ze.optional(),claudeModelHash:ze.optional()}).strict();function Pt(e){const t={app:zt.parse(e.app),endpoint:vt.shape.endpoint.parse(e.endpoint),key:vt.shape.key.parse(e.key),model:vt.shape.model.parse(e.model)};return`mdl_${m.createHash("sha256").update(JSON.stringify(t)).digest("hex")}`}const Mt=u.z.enum(["market","custom"]),Lt=u.z.enum(["active","deprecated","yanked"]),$t=u.z.discriminatedUnion("kind",[u.z.object({kind:u.z.literal("builtin"),key:u.z.string().trim().min(1).max(120)}).strict(),u.z.object({kind:u.z.literal("remote"),url:u.z.string().trim().url().max(2048),mediaType:u.z.enum(["image/png","image/jpeg","image/webp"]).optional(),digest:De.optional()}).strict()]),Ft=u.z.array(u.z.string().trim().min(1).max(80)).default([]),Ut=u.z.array(u.z.string().trim().min(1).max(120)).default([]),Vt=u.z.record(u.z.string().trim().min(2).max(35),u.z.string().trim().min(1).max(4096)),Ht=u.z.object({os:u.z.string().trim().min(1).max(40),architecture:u.z.string().trim().min(1).max(40),digest:De.optional(),downloadSizeBytes:u.z.number().int().positive().optional(),unpackedSizeBytes:u.z.number().int().positive().optional()}).strict(),qt=u.z.object({name:u.z.string().trim().min(1).max(128).regex(_e),version:u.z.string().trim().min(1).max(160).optional(),reference:Re,manifestDigest:De.optional(),publishedAt:Ne.optional(),platforms:u.z.array(Ht).default([]),status:Lt.default("active")}).strict(),Bt=u.z.object({id:ze,publisher:u.z.string().trim().min(1).max(160),slug:u.z.string().trim().min(1).max(160),name:u.z.string().trim().min(1).max(160),description:u.z.string().trim().min(1).max(4096),localizedDescriptions:Vt.optional(),cover:$t.optional(),repository:u.z.string().trim().min(1).max(512),defaultTag:u.z.string().trim().min(1).max(128).regex(_e),tags:u.z.array(qt).min(1),capabilities:Ft,optionalApps:Ut,defaultEnv:Se,labels:ve,status:Lt.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."})});u.z.object({protocolVersion:Ee,catalogId:ze,revision:u.z.string().trim().min(1).max(240),source:u.z.enum(["embedded","remote","cache"]),generatedAt:Ne,expiresAt:Ne.optional(),items:u.z.array(Bt)}).strict(),u.z.object({source:u.z.enum(["embedded","remote","cache"]),state:u.z.enum(["ready","refreshing","stale","failed"]),revision:u.z.string().trim().min(1).max(240),updatedAt:Ne,error:u.z.string().trim().max(4096).optional()}).strict(),u.z.object({id:ze,origin:u.z.literal("custom"),name:u.z.string().trim().min(1).max(160),description:u.z.string().trim().max(4096).optional(),localizedDescriptions:Vt.optional(),cover:$t.optional(),reference:Re,repository:u.z.string().trim().min(1).max(512),tag:u.z.string().trim().min(1).max(128).regex(_e).optional(),pullPolicy:u.z.literal("if-not-present").default("if-not-present"),capabilities:Ft,optionalApps:Ut,defaultEnv:Se,labels:ve,createdAt:Ne,updatedAt:Ne}).strict();const Kt=u.z.object({name:u.z.string().trim().min(1).max(128).regex(_e),version:u.z.string().trim().min(1).max(160).optional(),reference:Re,manifestDigest:De.optional(),status:Lt}).strict(),Gt=u.z.object({id:ze,origin:Mt,name:u.z.string().trim().min(1).max(160),description:u.z.string().trim().max(4096).optional(),localizedDescriptions:Vt.optional(),cover:$t,repository:u.z.string().trim().min(1).max(512),tag:u.z.string().trim().min(1).max(128).regex(_e).optional(),availableTags:u.z.array(Kt),reference:Re,digest:De.optional(),downloadSizeBytes:u.z.number().int().positive().optional(),unpackedSizeBytes:u.z.number().int().positive().optional(),capabilities:Ft,optionalApps:Ut,defaultEnv:Se,labels:ve,readOnly:u.z.boolean(),lifecycleStatus:Lt.optional(),market:u.z.object({catalogId:ze,catalogRevision:u.z.string().trim().min(1).max(240),publisher:u.z.string().trim().min(1).max(160),version:u.z.string().trim().min(1).max(160).optional()}).strict().optional()}).strict(),Jt=u.z.object({id:ze,origin:Mt,name:u.z.string().trim().min(1).max(160),description:u.z.string().trim().max(4096).optional(),localizedDescriptions:Vt.optional(),cover:$t.optional(),repository:u.z.string().trim().min(1).max(512),tag:u.z.string().trim().min(1).max(128).regex(_e).optional(),requestedReference:Re,resolvedDigest:De.optional(),resolvedReference:Re.optional(),downloadSizeBytes:u.z.number().int().positive().optional(),pullPolicy:u.z.literal("if-not-present").default("if-not-present"),capabilities:Ft,optionalApps:Ut,defaultEnv:Se,labels:ve,market:u.z.object({catalogId:ze,catalogRevision:u.z.string().trim().min(1).max(240),publisher:u.z.string().trim().min(1).max(160),version:u.z.string().trim().min(1).max(160).optional()}).strict().optional(),createdAt:Ne,updatedAt:Ne}).strict(),Wt=u.z.object({phase:u.z.enum(["checking-image","pulling-image","resolving-image","ready","failed"]),requestedReference:Re,generation:u.z.number().int().nonnegative().default(0),error:u.z.string().trim().max(4096).optional(),startedAt:Ne,updatedAt:Ne}).strict(),Yt="image.pull.terminal.output",Xt="image.pull.terminal.finished",Zt=u.z.object({instanceId:ze,generation:u.z.number().int().nonnegative(),requestedReference:Re,sequence:u.z.number().int().nonnegative(),observedAt:Ne}).strict(),Qt=Zt.extend({data:u.z.string().min(1).max(65536),replay:u.z.boolean().optional()}).strict(),en=Zt.extend({outcome:u.z.enum(["succeeded","failed"])}).strict();Zt.extend({status:u.z.enum(["connecting","pulling","extracting","complete","failed"]),layers:u.z.object({total:u.z.number().int().nonnegative(),completed:u.z.number().int().nonnegative(),downloaded:u.z.number().int().nonnegative(),downloading:u.z.number().int().nonnegative(),extracting:u.z.number().int().nonnegative()}).strict(),bytes:u.z.object({current:u.z.number().finite().nonnegative(),total:u.z.number().finite().positive()}).strict().optional(),percent:u.z.number().finite().min(0).max(100).optional(),message:u.z.string().trim().min(1).max(500),terminalTail:u.z.string().max(262144).optional(),terminalTruncated:u.z.boolean().optional()}).strict();const tn=u.z.object({id:ze,name:u.z.string().trim().min(1).max(160),connectionMode:u.z.enum(["local-ipc","local-loopback","direct-http","reverse-wss"]).default("direct-http"),auth:u.z.object({mode:u.z.enum(["local-static-key","paired-hmac"]).default("local-static-key"),keyId:ze.optional(),secret:u.z.string().trim().max(4096).optional(),pairedAt:Ne.optional(),pairing:u.z.object({status:u.z.enum(["pending","paired","expired"]).default("pending"),joinToken:u.z.string().trim().max(4096).optional(),expiresAt:Ne.optional()}).strict().optional()}).strict().default({mode:"local-static-key"}),endpoint:u.z.string().trim().max(2048).optional(),controlEndpoint:u.z.string().trim().max(2048).optional(),containerEndpoint:u.z.string().trim().max(2048).optional(),publicWebBase:u.z.string().trim().max(2048).optional(),status:u.z.enum(["unknown","online","offline","degraded"]).default("unknown"),health:u.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),capabilities:u.z.record(u.z.string(),u.z.unknown()).default({}),appInventory:Ve.optional(),labels:ve,lastSeenAt:Ne.optional(),createdAt:Ne,updatedAt:Ne}).strict(),nn=u.z.object({id:ze,nodeId:ze,name:u.z.string().trim().min(1).max(160),type:u.z.enum(["docker","kubernetes","local"]),status:u.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:u.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),capabilities:u.z.record(u.z.string(),u.z.unknown()).default({}),labels:ve,createdAt:Ne,updatedAt:Ne}).strict(),rn=u.z.object({instanceId:ze,runtimeKind:u.z.literal("docker"),state:u.z.enum(["pending","available","stopped","unavailable"]),sampledAt:Ne,cpu:u.z.object({usagePercent:u.z.number().nonnegative()}).strict().optional(),memory:u.z.object({usageBytes:u.z.number().nonnegative(),limitBytes:u.z.number().nonnegative().optional(),usagePercent:u.z.number().nonnegative().optional()}).strict().optional(),network:u.z.object({rxBytes:u.z.number().nonnegative(),txBytes:u.z.number().nonnegative()}).strict().optional(),blockIo:u.z.object({readBytes:u.z.number().nonnegative(),writeBytes:u.z.number().nonnegative()}).strict().optional(),pids:u.z.number().int().nonnegative().optional(),error:u.z.string().trim().max(2048).optional()}).strict();u.z.object({ok:u.z.boolean().optional(),role:u.z.string().optional(),nodeId:ze.optional(),platform:He.optional()}).passthrough();const sn=u.z.object({bindScope:u.z.enum(["loopback","all-ipv4"]),port:u.z.number().int().min(1).max(65535)}).strict(),on=sn.extend({host:u.z.enum(["127.0.0.1","0.0.0.0"]),status:u.z.enum(["listening","error"]),source:u.z.enum(["bootstrap","persisted"]),error:u.z.string().trim().max(2048).optional()}).strict(),an=sn;u.z.object({nodeId:ze,joinToken:u.z.string().trim().min(1),expiresAt:Ne}).passthrough(),u.z.object({id:ze,keyId:ze,url:u.z.string().trim().min(1).max(2048).optional(),name:u.z.string().trim().min(1).max(160).optional(),pairedAt:Ne,updatedAt:Ne.optional(),active:u.z.boolean().optional(),current:u.z.boolean().optional()}).passthrough(),u.z.object({remote:u.z.object({id:ze,url:u.z.string().trim().min(1).max(2048).optional(),keyId:ze,pairedAt:Ne,active:u.z.boolean()}).passthrough(),tunnel:u.z.object({status:u.z.enum(["disabled","saved","connecting","connected","failed"]),error:u.z.string().trim().max(2048).optional()}).passthrough()}).passthrough(),u.z.object({deleted:u.z.boolean().optional()}).passthrough();const cn=u.z.object({repository:u.z.string().trim().optional(),tag:u.z.string().trim().optional(),id:u.z.string().trim(),createdSince:u.z.string().trim().optional(),size:u.z.string().trim().optional(),sizeBytes:u.z.number().int().nonnegative().optional(),reference:u.z.string().trim().min(1),repoDigests:u.z.array(u.z.string().trim().min(1).max(512)).default([])}).passthrough();u.z.object({image:Gt,status:u.z.enum(["available","pull-required","unknown"]),localImage:cn.optional(),localSizeBytes:u.z.number().int().nonnegative().optional(),downloadSizeBytes:u.z.number().int().positive().optional(),unpackedSizeBytes:u.z.number().int().positive().optional(),error:u.z.string().trim().max(2048).optional()}).strict();const dn=u.z.lazy(()=>u.z.object({name:u.z.string().trim().min(1),path:u.z.string().trim().min(1).max(4096),children:u.z.array(dn)}).passthrough());u.z.object({status:u.z.number().int().min(100).max(599).optional(),headers:u.z.record(u.z.string(),u.z.string()).optional(),bodyBase64:u.z.string().optional()}).passthrough();const ln=u.z.object({strategy:u.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).default("node-proxy"),web:u.z.string().trim().max(2048).optional(),api:u.z.string().trim().max(2048).optional(),vnc:u.z.string().trim().max(2048).optional(),tty:u.z.string().trim().max(2048).optional(),logs:u.z.string().trim().max(2048).optional(),status:u.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict(),un=u.z.object({strategy:u.z.enum(["control-plane-proxy","direct-port","node-proxy","kubernetes-ingress","kubernetes-port-forward"]).default("control-plane-proxy"),web:u.z.string().trim().max(2048).optional(),api:u.z.string().trim().max(2048).optional(),ws:u.z.string().trim().max(2048).optional(),status:u.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown")}).strict().default({strategy:"control-plane-proxy",status:"unknown"}),mn=u.z.object({mode:u.z.enum(["local-bind","git-clone","empty-volume","persistent-volume"]).optional(),status:u.z.enum(["unknown","pending","ready","failed"]).default("unknown"),path:u.z.string().trim().max(4096).optional(),resolvedCommit:u.z.string().trim().max(120).optional(),error:u.z.string().trim().max(2048).optional()}).passthrough(),pn=u.z.object({id:ze,name:u.z.string().trim().min(1).max(160),projectId:ze.optional(),source:bt,sourceSnapshot:u.z.record(u.z.string(),u.z.unknown()).default({}),modelSelection:je,nodeId:ze,runtimeId:ze,imageSelection:Pe.optional(),imageSnapshot:Jt.optional(),imageProvisioning:Wt.optional(),stateRevision:u.z.number().int().min(0).default(0),status:u.z.enum(["created","provisioning","starting","registering","registered","running","stopping","stopped","failed","unhealthy"]).default("created"),health:u.z.enum(["unknown","ok","degraded","failed"]).default("unknown"),connectionStatus:u.z.enum(["unknown","online","offline","endpoint-unreachable"]).default("unknown"),agentStatus:u.z.enum(["unknown","online","offline"]).default("unknown"),targetStatus:u.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),uiAccessStatus:u.z.enum(["unknown","reachable","endpoint-unreachable"]).default("unknown"),controlMode:u.z.enum(["standalone","controlled"]).default("controlled"),protocolVersion:we.optional(),instanceVersion:u.z.string().trim().max(80).optional(),build:st.optional(),runtimeVersion:dt.optional(),ready:u.z.boolean().default(!1),capabilities:u.z.record(u.z.string(),u.z.unknown()).default({}),appInventory:Ve.optional(),config:u.z.object({autoImportAgentConfigs:u.z.boolean().default(!0),defaultCodexPermissionMode:L.default("ask")}).strict().default({autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"}),workspace:mn.default({status:"unknown"}),target:ln.default({strategy:"direct-port",status:"unknown"}),access:un,apps:u.z.object({runningCount:u.z.number().int().min(0).default(0),problemCount:u.z.number().int().min(0).default(0),updatedAt:Ne.optional(),revision:u.z.number().int().min(0).optional()}).strict().default({runningCount:0,problemCount:0}),aiSessions:ne.default(()=>({runningCount:0,waitingCount:0,staleCount:0,sessions:[],updatedAt:(new Date).toISOString()})),triggers:u.z.object({enabledCount:u.z.number().int().min(0).default(0),runningCount:u.z.number().int().min(0).default(0),errorCount:u.z.number().int().min(0).default(0),configs:u.z.array(u.z.object({configHash:u.z.string().trim().min(1),config:he,deployments:u.z.array(Ie).default([]),runtime:u.z.array(ye).default([])}).strict()).default([]),recentRuns:u.z.array(Ae).default([])}).strict().optional(),runtime:u.z.object({kind:u.z.string().trim().max(80).optional(),containerName:u.z.string().trim().max(240).optional(),containerId:u.z.string().trim().max(240).optional(),workspacePath:u.z.string().trim().max(4096).optional(),pid:u.z.number().int().positive().optional(),port:u.z.number().int().positive().max(65535).optional(),labels:u.z.record(u.z.string(),u.z.string()).default({})}).strict().default({labels:{}}),registrationToken:u.z.string().trim().min(1).max(240).optional(),lastHeartbeatAt:Ne.optional(),createdAt:Ne,updatedAt:Ne}).strict(),gn="instance.lifecycle.snapshot",hn=u.z.object({instanceId:pn.shape.id,revision:u.z.number().int().min(0),updatedAt:Ne,status:pn.shape.status.unwrap(),health:pn.shape.health.unwrap(),connectionStatus:pn.shape.connectionStatus.unwrap(),accessStatus:u.z.enum(["reachable","endpoint-unreachable"]),imageProvisioning:Wt.optional(),workspace:mn,runtime:pn.shape.runtime.unwrap(),runtimeVersion:dt.optional(),ready:u.z.boolean(),lastHeartbeatAt:Ne.optional()}).strict();function fn(e,t){return pn.safeParse(In(e,t))}function In(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=e,i=new Set(Object.keys(pn.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=bn(e,["id","name","kind","source","availability","diagnosticCode"]);return!i||"object"!=typeof i||Array.isArray(i)?i:{...i,capabilities:bn(e.capabilities,["automation","supportsCwdSelection"])}}):i.items,issues:Array.isArray(i.issues)?i.issues.map(e=>bn(e,["code","message"])):i.issues},s=Ve.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=bt.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=bn(i,o);if("local-folder"!==r){const e=yn(ft,bn(i.ref,["type","name","commit"]),"source.ref",t,n),r=yn(It,bn(i.auth,["type","secretId"]),"source.auth",t,n),s=yn(yt,bn(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=yn(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=yn(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=yn(te,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:Ne.safeParse(i.updatedAt).success?i.updatedAt:(new Date).toISOString()};return Object.keys(i).some(e=>!["runningCount","waitingCount","staleCount","sessions","updatedAt"].includes(e))&&t?.({instanceId:n,field:"aiSessions"}),ne.parse(s)}(n.aiSessions,t,"string"==typeof n.id?n.id:void 0),r.triggers=function(e,t,n){if(!e||"object"!=typeof e||Array.isArray(e))return;const i=e;Object.keys(i).some(e=>!["enabledCount","runningCount","errorCount","configs","recentRuns"].includes(e))&&t?.({instanceId:n,field:"triggers"});const r=(e,i,r)=>Array.isArray(e)?e.flatMap((e,s)=>{const o=yn(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=bn(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=bn(e,t)}return s.action=bn(r.action,["promptTemplate"]),s.policy=bn(r.policy,["cooldownMs","maxConcurrentRuns","whenBusy"]),yn(he,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,Ie,`triggers.configs.${i}.deployments`),runtime:r(s.runtime,ye,`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,Ae,"triggers.recentRuns")}}(n.triggers,t,"string"==typeof n.id?n.id:void 0),r.apps=yn(pn.shape.apps.unwrap(),bn(n.apps,["runningCount","problemCount","updatedAt","revision"]),"apps",t,"string"==typeof n.id?n.id:void 0)||{runningCount:0,problemCount:0},r.config=yn(pn.shape.config.unwrap(),bn(n.config,["autoImportAgentConfigs","defaultCodexPermissionMode"]),"config",t,"string"==typeof n.id?n.id:void 0)||{autoImportAgentConfigs:!0,defaultCodexPermissionMode:"ask"},r.modelSelection=yn(je.unwrap(),bn(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=Ce(s)}catch{if(!s.includes("@")&&s.lastIndexOf(":")<=s.lastIndexOf("/"))try{s=Ce(`${s}:latest`)}catch{}}try{r=s?Oe(s):void 0}catch{}return{id:t.id,origin:"custom",name:t.name,description:t.description,localizedDescriptions:t.localizedDescriptions,cover:bn(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?Oe(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?bn(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=bn(n.imageSelection,["imageId","tag"]);r.imageSelection=o||(s?{imageId:s,tag:r.imageSnapshot?.tag}:void 0),r.imageProvisioning=yn(Wt,bn(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(dt.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(ct.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=Ne.safeParse(i.lastAttemptAt),m=Ne.safeParse(i.matchedAt);return void 0===i.lastAttemptAt||u.success||t?.({instanceId:n,field:"runtimeVersion.lastAttemptAt"}),void 0===i.matchedAt||m.success||t?.({instanceId:n,field:"runtimeVersion.matchedAt"}),{desiredVersion:s,...l?{actualVersion:l}:{},phase:c,attempt:"number"==typeof i.attempt&&Number.isInteger(i.attempt)&&i.attempt>=0?i.attempt:0,...u.success?{lastAttemptAt:u.data}:{},...m.success?{matchedAt:m.data}:{},...d?{error:d}:{}}}(n.runtimeVersion,t,"string"==typeof n.id?n.id:void 0),r.workspace=yn(mn,n.workspace,"workspace",t,"string"==typeof n.id?n.id:void 0)||{status:"unknown"},r.runtime=yn(pn.shape.runtime.unwrap(),bn(n.runtime,["kind","containerName","containerId","workspacePath","pid","port","labels"]),"runtime",t,"string"==typeof n.id?n.id:void 0)||{labels:{}},r.target=yn(ln,bn(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=yn(un,bn(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(pn.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 yn(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=An(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=An(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 An(e,t){let n=e;for(const e of t){if(!n||"object"!=typeof n)return;n=n[e]}return n}function bn(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 wn=u.z.object({instanceId:ze.optional(),name:u.z.string().trim().min(1).max(160),projectId:ze.optional(),source:bt.optional(),nodeId:ze.optional(),runtimeId:ze.optional(),imageSelection:Pe.optional(),instanceVersion:u.z.string().trim().max(80).optional(),protocolVersion:we,build:st.optional(),controlMode:u.z.enum(["standalone","controlled"]).default("controlled"),capabilities:u.z.record(u.z.string(),u.z.unknown()).default({}),appInventory:Ve.optional(),target:ln.default({strategy:"direct-port",status:"unknown"}),workspace:mn.default({status:"unknown"}),registrationToken:u.z.string().trim().max(240).optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==be||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol register payload requires appInventory."})}),zn=u.z.object({status:pn.shape.status.optional(),health:pn.shape.health.optional(),protocolVersion:we,build:st.optional(),capabilities:pn.shape.capabilities.optional(),appInventory:Ve.optional(),apps:pn.shape.apps.optional(),aiSessions:pn.shape.aiSessions.optional(),triggers:pn.shape.triggers.optional(),workspace:mn.optional(),target:ln.partial().optional()}).strict().superRefine((e,t)=>{e.protocolVersion!==be||e.appInventory||t.addIssue({code:"custom",path:["appInventory"],message:"Current protocol heartbeat payload requires appInventory."})}),Nn=u.z.enum(["web","telegram","wechat","dingding"]);function vn(e){return e.readyState===(e.OPEN??1)}function Sn(e,t,n){e.close(function(e){if("number"==typeof e&&Number.isInteger(e))return e>=3e3&&e<=4999||e>=1e3&&e<=1014&&1004!==e&&1005!==e&&1006!==e?e:void 0}(t),function(e){const t=Buffer.isBuffer(e)?e.toString("utf8"):"string"==typeof e?e:"";if(Buffer.byteLength(t,"utf8")<=123)return t;let n="";for(const e of t){const t=`${n}${e}`;if(Buffer.byteLength(t,"utf8")>123)break;n=t}return n}(n)||void 0)}function En(e,t){e.send(t.data,{binary:t.isBinary})}function _n(e,t){if(vn(e))for(const n of t.splice(0))En(e,n)}function Tn(e,t,n={}){return new Promise((i,r)=>{const s=o.spawn(e,t,{stdio:["ignore","pipe","pipe"]}),a=[],c=[];let d=!1;const l=n.timeoutMs?setTimeout(()=>{d=!0,s.kill("SIGKILL")},n.timeoutMs):void 0;l?.unref?.(),s.stdout.on("data",e=>a.push(Buffer.from(e))),s.stderr.on("data",e=>c.push(Buffer.from(e))),s.on("error",e=>{l&&clearTimeout(l),r(e)}),s.on("close",t=>{l&&clearTimeout(l);const s={stdout:Buffer.concat(a).toString("utf8").trim(),stderr:Buffer.concat(c).toString("utf8").trim()};if(d){const t=new Error(`${e} timed out after ${n.timeoutMs}ms`);return Object.assign(t,{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:s}),void r(t)}if(0===t)return void i(s);const o=new Error(s.stderr||`${e} exited with code ${t}`);Object.assign(o,{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:s}),r(o)})})}u.z.object({id:ze,channel:Nn,name:u.z.string().trim().min(1).max(160),enabled:u.z.boolean().default(!1),token:u.z.string().trim().max(4096).optional(),defaultChatId:u.z.string().trim().max(240).optional(),allowedUserIds:u.z.array(u.z.string().trim().min(1).max(240)).default([]),pollIntervalMs:u.z.number().int().positive().max(6e4).default(3e3),settings:u.z.record(u.z.string(),u.z.unknown()).default({}),createdAt:Ne,updatedAt:Ne}).strict(),u.z.object({id:ze,channel:Nn,bridgeId:ze.optional(),chatSessionId:u.z.string().trim().min(1).max(240),userId:u.z.string().trim().max(240).optional(),activeProjectId:ze.optional(),activeInstanceId:ze.optional(),activeAiSessionId:u.z.string().trim().min(1).max(120).optional(),lastUsedAt:Ne,createdAt:Ne,updatedAt:Ne}).strict(),u.z.object({source:u.z.object({type:u.z.literal("chat-gateway").default("chat-gateway"),channel:Nn,bridgeId:ze.optional(),chatSessionId:u.z.string().trim().min(1).max(240),userId:u.z.string().trim().max(240).optional()}).strict(),message:u.z.object({text:u.z.string().trim().max(2e4).default(""),attachments:u.z.array(D).max(6).default([])}).strict().superRefine((e,t)=>{e.attachments.reduce((e,t)=>e+("inline"===t.source.type?t.size:0),0)>w&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["attachments"],message:"Inline attachments must be 41943040 bytes or less in total."})}),target:u.z.object({instanceId:ze,aiSessionId:u.z.string().trim().min(1).max(120)}).strict().optional()}).strict(),u.z.object({id:ze,instanceId:ze,projectId:ze.optional(),aiSessionId:u.z.string().trim().min(1).max(120),providerSessionId:u.z.string().trim().max(240).optional(),result:u.z.string().default(""),timeoutMs:u.z.number().positive().optional(),source:u.z.string().trim().max(120).optional(),kind:u.z.enum(["task","approval"]).default("task"),status:u.z.enum(["pending","unreachable"]).default("pending"),error:u.z.string().trim().max(2048).optional(),lastSeenAt:Ne}).strict();const kn=(e,t,n={})=>new Promise((i,r)=>{const s=[];let o,a=!1;try{o=p.spawn(e,t,{name:"xterm-256color",cols:n.cols||120,rows:n.rows||40,cwd:process.cwd(),env:process.env})}catch(e){return void r(e)}const c=n.timeoutMs?setTimeout(()=>{a=!0,o.kill("SIGKILL")},n.timeoutMs):void 0;c?.unref?.(),o.onData(e=>{s.push(e),n.onData?.(e)}),o.onExit(({exitCode:t})=>{c&&clearTimeout(c);const o={stdout:s.join(""),stderr:""};a?r(Object.assign(new Error(`${e} timed out after ${n.timeoutMs}ms`),{statusCode:504,code:"RUNTIME_COMMAND_TIMEOUT",details:o})):0!==t?r(Object.assign(new Error(o.stdout.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g,"").split(/\r?\n/).map(e=>e.trim()).filter(Boolean).at(-1)||`${e} exited with code ${t}`),{statusCode:502,code:"RUNTIME_EXECUTOR_FAILED",details:o})):i(o)})});class xn{inFlight=new Map;runCommand;runTerminalCommand;constructor(e=Tn,t){this.runCommand=e,this.runTerminalCommand=t||function(e){return e===Tn?kn:async(t,n,i={})=>{const r=await e(t,n,{timeoutMs:i.timeoutMs});return r.stdout&&i.onData?.(r.stdout),r.stderr&&i.onData?.(r.stderr),r}}(e)}ensure(e,t,n){const i=Ce(e),r=this.inFlight.get(i);if(r)return t&&(r.phaseListeners.add(t),r.phase&&t(r.phase)),n&&(r.terminalListeners.add(n),r.terminalTail&&n({sequence:r.terminalSequence,data:r.terminalTail,replay:!0})),r.promise;const s=new Set,o=new Set;t&&s.add(t),n&&o.add(n);const a={promise:Promise.resolve(void 0),phaseListeners:s,terminalListeners:o,terminalSequence:0,terminalTail:""};return a.promise=this.ensureOnce(i,e=>{a.phase=e,s.forEach(t=>t(e))},e=>{a.terminalSequence+=1,a.terminalTail=`${a.terminalTail}${e}`.slice(-262144);const t={sequence:a.terminalSequence,data:e};o.forEach(e=>e(t))}).finally(()=>this.inFlight.delete(i)),this.inFlight.set(i,a),a.promise}async ensureOnce(e,t,n){t("checking-image");let i=await this.inspect(e).catch(()=>{}),r=!1;i||(t("pulling-image"),await this.runTerminalCommand("docker",["pull",e],{cols:120,rows:40,onData:n}),r=!0,i=await this.inspect(e)),t("resolving-image");const s=(o=i,Array.isArray(o.RepoDigests)?o.RepoDigests.filter(e=>"string"==typeof e):[]).find(e=>/@sha256:[a-fA-F0-9]{64}$/.test(e));var o;const a=s?.split("@").at(-1)?.toLowerCase();return{requestedReference:e,...a?{resolvedDigest:a}:{},resolvedReference:s||e,pulled:r}}async inspect(e){const t=await this.runCommand("docker",["image","inspect",e,"--format","{{json .}}"]);return JSON.parse(t.stdout.trim()||"{}")}}function Cn(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 On{runCommand;publishHost;images;launcherAssetsDir;constructor(e=Tn,i={}){this.runCommand=e,this.images=i.imageService||new xn(e),this.publishHost=i.publishHost||"127.0.0.1",this.launcherAssetsDir=i.launcherAssetsDir||function(){const e=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,i=[n.resolve(e,"../../../../../docker"),n.resolve(e,"../docker"),n.resolve(e,"../../docker")];return i.find(e=>t.existsSync(n.join(e,"runtime-installer.mjs")))||i[0]}()}async start(e){Mn(e);const t=e.instance.runtime.containerName||Pn(e.instance.id);if(await this.runCommand("docker",["start",t]).catch(()=>{}))return this.runningResult(e,t,e.instance.runtime.containerId);await this.images.ensure(e.image.resolvedReference||e.image.requestedReference);const n=await this.runCommand("docker",function(e,t,n={}){const i=n.publishHost||"127.0.0.1",r=e.node?.id||"node_unset",s=e.runtime?.id||"runtime_local_docker",o=["run","-d","--name",t,"--label",`task-handoff.instance-id=${e.instance.id}`,"--label",`task-handoff.project-id=${e.project.id}`,"--label",`task-handoff.node-id=${r}`,"--label",`task-handoff.runtime-id=${s}`,"--label",`task-handoff.image-id=${e.image.id}`,"--shm-size","1gb","--security-opt","seccomp=unconfined","--network","bridge","--add-host","host.docker.internal:host-gateway","--tmpfs","/tmp:rw,mode=1777","-v",`${t}-data:/data`,"-v",`${t}-agent-home:/home/agent`,"-p",`${i}::8080`,"-e","TASK_HANDOFF_CONTROL_MODE=controlled","-e",`TASK_HANDOFF_NODE_AGENT_URL=${e.nodeAgentUrl||e.node?.endpoint||""}`,"-e",`TASK_HANDOFF_INSTANCE_ID=${e.instance.id}`,"-e",`TASK_HANDOFF_INSTANCE_NAME=${e.instance.name}`,"-e",`TASK_HANDOFF_REGISTRATION_TOKEN=${e.instance.registrationToken||""}`,"-e",`TASK_HANDOFF_PROJECT_ID=${e.project.id}`,"-e",`TASK_HANDOFF_NODE_ID=${r}`,"-e",`TASK_HANDOFF_RUNTIME_ID=${s}`,"-e",`TASK_HANDOFF_IMAGE_ID=${e.image.id}`,...e.image.tag?[`TASK_HANDOFF_IMAGE_TAG=${e.image.tag}`]:[],"-e","TASK_HANDOFF_CHAT_BRIDGES=none","-e",`TASK_HANDOFF_WORKSPACE=${e.project.workspacePolicy.path||"/workspace"}`,"-e",`TASK_HANDOFF_WORKSPACE_MODE=${e.project.workspacePolicy.mode}`];"local-folder"===e.project.source.type?o.push("-v",`${e.project.source.path}:${e.project.workspacePolicy.path||"/workspace"}:${e.project.workspacePolicy.readOnly?"ro":"rw"}`):(o.push("-e",`TASK_HANDOFF_PROJECT_SOURCE=${JSON.stringify(e.project.source)}`),o.push("-e",`TASK_HANDOFF_WORKSPACE_POLICY=${JSON.stringify(e.project.workspacePolicy)}`),o.push("-e",`TASK_HANDOFF_GIT_URL=${e.project.source.url}`),e.project.source.ref?.commit?o.push("-e",`TASK_HANDOFF_GIT_COMMIT=${e.project.source.ref.commit}`):e.project.source.ref?.name&&o.push("-e",`TASK_HANDOFF_GIT_REF=${e.project.source.ref.name}`),e.project.source.clone?.depth&&o.push("-e",`TASK_HANDOFF_GIT_DEPTH=${e.project.source.clone.depth}`),o.push("-e","TASK_HANDOFF_GIT_SUBMODULES="+(e.project.source.clone?.submodules?"true":"false")),o.push("-e","TASK_HANDOFF_GIT_LFS="+(e.project.source.clone?.lfs?"true":"false")),e.project.source.clone?.subdirectory&&o.push("-e",`TASK_HANDOFF_WORKSPACE_SUBDIRECTORY=${e.project.source.clone.subdirectory}`));for(const[t,n]of Object.entries(e.image.defaultEnv))o.push("-e",`${t}=${n}`);for(const[t,n]of Object.entries(e.modelEnv||{}))o.push("-e",`${t}=${n}`);return o.push(e.image.resolvedReference||e.image.requestedReference),o}(e,t,{publishHost:this.publishHost}));return this.runningResult(e,t,n.stdout||void 0)}async runningResult(e,t,n){const i=await this.containerPort(t,"8080/tcp"),r=i?`http://127.0.0.1:${i}`:void 0,s=e.node?.id||"node_unset",o=e.runtime?.id||"runtime_local_docker";return{status:"registering",health:"unknown",connectionStatus:r?"online":"unknown",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:r?"reachable":"unknown",...r?{web:r,api:`${r}/api`}:{}},workspace:{mode:e.project.workspacePolicy.mode,status:"pending",path:e.project.workspacePolicy.path},runtime:{...e.instance.runtime,kind:"docker",containerName:t,...n?{containerId:n}:{},labels:{...e.instance.runtime.labels,"task-handoff.instance-id":e.instance.id,"task-handoff.project-id":e.project.id,"task-handoff.node-id":s,"task-handoff.runtime-id":o,"task-handoff.image-id":e.image.id}}}}async stop(e){return await this.runCommand("docker",["stop",e.instance.runtime.containerName||Pn(e.instance.id)]).catch(()=>({stdout:"",stderr:""})),{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async restart(e,t){Mn(e);const n=e.instance.runtime.containerName||Pn(e.instance.id),i=await this.inspectContainerId(n);if(!i)throw Rn("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${n} does not exist.`);Dn(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 Rn("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while restarting ${n}.`);return Dn(n,r,t,"after restart","INSTANCE_RUNTIME_RESTART_FAILED"),this.runningResult(e,n,r)}async delete(e){return await this.runCommand("docker",["rm","-f",e.instance.runtime.containerName||Pn(e.instance.id)]).catch(()=>({stdout:"",stderr:""})),{status:"stopped",health:"unknown",connectionStatus:"offline",target:{...e.instance.target,status:"unknown"},runtime:e.instance.runtime}}async installRuntime(e){const t=await this.installRuntimeRelease(e);Dn(e.containerName,t,e.expectedContainerId,"before runtime restart","INSTANCE_RUNTIME_RESTART_FAILED");try{await this.runCommand("docker",["restart",e.containerName])}catch(t){throw Rn("INSTANCE_RUNTIME_RESTART_FAILED",`Could not restart Docker container ${e.containerName}.`,t)}const n=await this.inspectContainerId(e.containerName);if(!n||n!==t)throw Rn("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while updating ${e.containerName}.`);return Dn(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 Rn("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container ${e.containerName} does not exist.`);Dn(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 Rn("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 Rn("INSTANCE_RUNTIME_INSTALL_FAILED",`Docker container identity changed while installing ${e.containerName}.`);return Dn(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=at.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 Rn("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 Rn("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker reported an unsupported runtime target ${String(t||"unknown")}/${String(n||"unknown")}.`);return{platform:i,arch:s,launcherAbi:1}}async rollbackRuntime(e){const t=await this.inspectContainerId(e);if(!t)throw Rn("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container ${e} does not exist.`);try{await this.runCommand("docker",["exec","--user","0",e,"task-handoff-runtime","rollback"]),await this.runCommand("docker",["restart",e])}catch(t){throw Rn("INSTANCE_RUNTIME_RESTART_FAILED",`Could not roll back ${e} to its previous controlled-instance release.`,t)}const n=await this.inspectContainerId(e);if(!n||n!==t)throw Rn("INSTANCE_RUNTIME_RESTART_FAILED",`Docker container identity changed while rolling back ${e}.`);return this.inspectRuntimeVersion(e)}async installRuntimeLauncher(e){const t=await this.inspectContainerId(e);if(!t)throw Rn("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 Rn("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Could not install the runtime launcher in ${e}.`,t)}if(await this.inspectContainerId(e)!==t)throw Rn("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Docker container identity changed while installing the runtime launcher in ${e}.`)}async inspectContainerId(e){const t=await this.runCommand("docker",["inspect","--format","{{.Id}}",e]).catch(()=>{});return t?.stdout.trim()||void 0}async containerPort(e,t){const n=(await this.runCommand("docker",["port",e,t]).catch(()=>({stdout:"",stderr:""}))).stdout.split(/\r?\n/).find(Boolean),i=n?.match(/:(\d+)$/);return i?.[1]}}function Rn(e,t,n){const i=function(e){if(!e||"object"!=typeof e)return void 0===e?void 0:String(e);const t=e,n=t.details?.stderr||t.details?.stdout;return"string"==typeof n&&n.trim()?n.trim():"string"==typeof t.message&&t.message.trim()?t.message.trim():void 0}(n),r=new Error(i?`${t} Cause: ${i}`:t,void 0===n?void 0:{cause:n});return Object.assign(r,{statusCode:502,code:e}),r}function Dn(e,t,n,i,r){if(n&&t!==n)throw Rn(r,`Docker container ${e} identity mismatch ${i}: expected ${n}, got ${t}.`)}async function jn(e=Tn){return async function(e=Tn){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:Cn(t.Size),reference:s,repoDigests:o}}).filter(e=>Boolean(e.reference))}(e)}function Pn(e){return`task-handoff-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`}function Mn(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 Ln=u.z.enum(["created","starting","running","stopping","stopped","exited","failed","closed","terminated","unknown"]),$n=u.z.object({type:u.z.enum(["app-session","provider-session","adapter-key"]),id:u.z.string().trim().min(1).max(240),agent:u.z.string().trim().min(1).max(80).optional(),adapter:u.z.string().trim().min(1).max(80).optional(),key:u.z.string().trim().min(1).max(240).optional()}).strict(),Fn=u.z.record(u.z.string(),u.z.unknown()).and(u.z.object({id:u.z.string().trim().min(1).max(160),appId:u.z.string().trim().min(1).max(160).optional(),title:u.z.string().trim().max(240).optional(),kind:u.z.string().trim().max(80).optional(),status:Ln.default("unknown"),bindings:u.z.array($n).max(40).default([]),workspace:u.z.object({cwd:u.z.string().trim().max(4096).optional()}).strict().optional(),createdAt:u.z.string().datetime().optional(),updatedAt:u.z.string().datetime().optional()})),Un=u.z.object({runningCount:u.z.number().int().min(0).default(0),problemCount:u.z.number().int().min(0).default(0),sessions:u.z.array(Fn).default([]),updatedAt:u.z.string().datetime()}).strict();u.z.object({streamId:u.z.string().trim().min(1).max(240),revision:u.z.number().int().min(0),lastEventAt:u.z.string().datetime(),snapshot:Un}).strict(),Un.pick({runningCount:!0,problemCount:!0,updatedAt:!0}).extend({revision:u.z.number().int().min(0).optional()});const Vn=u.z.enum(["app-session-created","app-session-updated","app-session-deleted","app-session-recovered","control-action","heartbeat-sync","startup"]),Hn=u.z.object({streamId:u.z.string().trim().min(1).max(240),instanceId:u.z.string().trim().min(1).max(160),nodeId:u.z.string().trim().min(1).max(160).optional(),revision:u.z.number().int().min(0),previousRevision:u.z.number().int().min(0).optional(),traceId:u.z.string().trim().min(1).max(160),generatedAt:u.z.string().datetime(),reason:Vn}).strict(),qn=u.z.object({meta:Hn,snapshot:Un}).strict(),Bn=u.z.object({meta:Hn,session:Fn}).strict(),Kn=u.z.object({meta:Hn,sessionId:u.z.string().trim().min(1).max(160),tombstone:Fn.optional(),expiresAt:u.z.string().datetime().optional()}).strict();function Gn(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"}u.z.object({streamId:u.z.string().trim().min(1).max(240),instanceId:u.z.string().trim().min(1).max(160),sinceRevision:u.z.number().int().min(0),latestRevision:u.z.number().int().min(0),earliestRetainedRevision:u.z.number().int().min(0),syncRequired:u.z.boolean().default(!1),events:u.z.array(u.z.discriminatedUnion("type",[u.z.object({type:u.z.literal("app-session.snapshot"),payload:qn}).strict(),u.z.object({type:u.z.literal("app-session.patch"),payload:Bn}).strict(),u.z.object({type:u.z.literal("app-session.removed"),payload:Kn}).strict()])).default([])}).strict();const Jn=u.z.enum(["ai.sessions","app.sessions"]),Wn=u.z.object({topic:Jn,instanceId:u.z.string().trim().min(1).max(160),streamId:u.z.string().trim().min(1).max(240),latestRevision:u.z.number().int().min(0),earliestRetainedRevision:u.z.number().int().min(0)}).strict(),Yn=u.z.object({protocolVersion:u.z.literal(1),streams:u.z.array(Wn)}).strict();class Xn{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 Zn(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}class Qn{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 l(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=ei(t);n?this.sendForwarded(e,this.createEvent(gn,n,{instanceId:t.id})):this.logger?.warn?.({instanceId:t.id},"instance.lifecycle.snapshot.invalid")}for(const[t,n]of this.imagePullTerminalByInstance)Zn(n.tail).forEach((i,r)=>this.sendForwarded(e,this.createEvent(Yt,{...n.output,sequence:n.output.sequence+r,data:i,...0===r?{replay:!0}:{}},{instanceId:t}))),n.finished&&this.sendForwarded(e,this.createEvent(Xt,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===Yt){const e=Qt.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===Xt){const e=en.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(gn,function(e){return hn.parse(ti(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:Gn(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===l.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=ii(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 Xn,url:t}),i.readyState===l.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:Gn(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=Yn.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===l.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===l.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&&ii(t);if(!n||!this.outputs.size)return;const i=this.retries.get(e)??{timer:new Xn};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=ni(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=ni(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 ei(e){const t=hn.safeParse(ti(e));return t.success?t.data:void 0}function ti(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 ni(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 ii(e){const t=e.target?.api||e.target?.web;if(t)try{const e=new URL("/api/events",t);return e.protocol="https:"===e.protocol?"wss:":"ws:",e.toString()}catch{return}}const ri=new Set(["provisioning","starting","registering","registered","running","unhealthy"]),si=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;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 ri.has(t.status)?(await this.collect([t]),this.snapshots.get(e)):ui(t.id)}async collect(e){const t=e||this.targets();if(!e){const e=new Set(t.map(e=>e.id));for(const t of this.snapshots.keys())e.has(t)||this.snapshots.delete(t)}for(const e of t)this.pendingTargets.set(e.id,e);this.inFlight||(this.inFlight=this.drain().finally(()=>{this.inFlight=void 0})),await this.inFlight,this.pendingTargets.size&&await this.collect([])}async drain(){for(;this.pendingTargets.size;){const e=[...this.pendingTargets.values()];this.pendingTargets.clear(),await this.collectOnce(e)}}async collectOnce(e){const t=e.filter(e=>ri.has(e.status)&&(e.runtime.containerId||e.runtime.containerName));for(const t of e.filter(e=>ri.has(e.status)&&!e.runtime.containerId&&!e.runtime.containerName))this.update(mi(t.id));for(const t of e.filter(e=>!ri.has(e.status)))this.update(ui(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",si,...n],{timeoutMs:5e3});this.applyDockerOutput(t,e.stdout,i)}catch(e){if(1===t.length)return void this.update(pi(t[0].id,i,e instanceof Error?e.message:String(e)));await Promise.all(t.map(async e=>{const t=e.runtime.containerId||e.runtime.containerName;try{const n=await this.runCommand("docker",["stats","--no-stream","--format",si,t],{timeoutMs:5e3});this.applyDockerOutput([e],n.stdout,i)}catch(t){this.update(pi(e.id,i,t instanceof Error?t.message:String(t)))}}))}}applyDockerOutput(e,t,n){const i=function(e,t=(new Date).toISOString()){const n=new Map;for(const i of e.split(/\r?\n/).filter(Boolean)){let e;try{e=JSON.parse(i)}catch{continue}const r=li(e.id),s=li(e.name),o=r||s;if(!o)continue;const a=ai(li(e.memory)),c=ai(li(e.network)),d=ai(li(e.blockIo)),l=rn.parse({instanceId:o,runtimeKind:"docker",state:"available",sampledAt:t,cpu:ci(e.cpu,"usagePercent"),memory:a?{usageBytes:a[0],...void 0!==a[1]?{limitBytes:a[1]}:{},...ci(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:di(e.pids)});r&&n.set(r,l),s&&n.set(s,l)}return n}(t,n);for(const t of e){const e=[t.runtime.containerId,t.runtime.containerName].filter(Boolean),r=[...i.entries()].find(([t])=>e.some(e=>e===t||e.startsWith(t)||t.startsWith(e)))?.[1];this.update(r?{...r,instanceId:t.id}:pi(t.id,n,"Container metrics were not returned by Docker."))}}update(e){const t=rn.parse(e);this.snapshots.set(t.instanceId,t),this.publish?.(t)}}function ai(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 ci(e,t){const n=Number(li(e).replace(/%$/,""));return Number.isFinite(n)&&n>=0?{[t]:n}:void 0}function di(e){const t=Number(li(e));return Number.isFinite(t)&&t>=0?t:void 0}function li(e){return"string"==typeof e||"number"==typeof e?String(e).trim():""}function ui(e){return{instanceId:e,runtimeKind:"docker",state:"stopped",sampledAt:(new Date).toISOString()}}function mi(e){return{instanceId:e,runtimeKind:"docker",state:"pending",sampledAt:(new Date).toISOString()}}function pi(e,t,n){return{instanceId:e,runtimeKind:"docker",state:"unavailable",sampledAt:t,error:n.slice(0,2048)}}function gi(e){try{return t.statSync(e).isDirectory()}catch{return!1}}function hi(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()&&gi(n.join(s,e.name))).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,80).flatMap(e=>{const t=hi(n.join(s,e.name),i-1);return t?[t]:[]}):[];return{name:o,path:s,children:c}}function fi(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(gi)}()).flatMap(t=>{const n=hi(t,e.depth);return n?[n]:[]})}const Ii=u.z.object({path:u.z.string().trim().min(1).max(2048),method:u.z.string().trim().min(1).max(20).default("GET"),headers:u.z.record(u.z.string(),u.z.string()).default({}),body:u.z.string().optional(),bodyBase64:u.z.string().optional()}).strict(),yi=u.z.object({id:u.z.string().trim().min(1).max(120).optional(),name:u.z.string().trim().min(1).max(160),path:u.z.string().trim().min(1).max(4096),defaultImageSelection:Pe.optional(),labels:u.z.record(u.z.string(),u.z.string()).default({})}).strict(),Ai=u.z.object({path:u.z.string().trim().min(1).max(4096).optional(),depth:u.z.coerce.number().int().min(0).max(1).default(0)}).strict(),bi=u.z.object({id:u.z.string().trim().min(1).max(120).optional(),name:u.z.string().trim().min(1).max(160).optional(),runtimeId:u.z.string().trim().min(1).max(120),imageSelection:Pe.optional(),projectId:u.z.string().trim().min(1).max(120).optional(),image:Jt.optional(),source:bt,sourceSnapshot:u.z.record(u.z.string(),u.z.unknown()).default({}),config:u.z.object({autoImportAgentConfigs:u.z.boolean().optional(),defaultCodexPermissionMode:L.optional()}).strict().optional(),modelSelection:pn.shape.modelSelection}).strict(),wi=u.z.object({name:u.z.string().trim().min(1).max(160).optional(),config:u.z.object({autoImportAgentConfigs:u.z.boolean().optional(),defaultCodexPermissionMode:L.optional()}).strict().optional(),modelSelection:pn.shape.modelSelection.optional()}).strict(),zi=u.z.object({id:u.z.string().trim().min(1).max(120).optional(),name:u.z.string().trim().min(1).max(160),type:u.z.enum(["docker","kubernetes","local"]),status:u.z.enum(["unknown","online","offline","degraded"]).default("unknown"),accessStrategy:u.z.enum(["node-proxy","direct-port","kubernetes-ingress","kubernetes-port-forward"]).optional(),capabilities:u.z.record(u.z.string(),u.z.unknown()).default({}),labels:u.z.record(u.z.string(),u.z.string()).default({})}).strict(),Ni=zi.omit({id:!0}).partial().strict();function vi(){return process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR||n.join(g.homedir(),".config","task-handoff","node-agent")}function Si(e=vi()){const t=n.resolve(e);return{dataDir:t,identityPath:n.join(t,"identity.json"),settingsPath:n.join(t,"runtime-settings.json"),localFoldersDir:n.join(t,"local-folders"),nodeRuntimesDir:n.join(t,"node-runtimes"),controlledInstancesDir:n.join(t,"controlled-instances"),nodeModelsDir:n.join(t,"models"),modelAssignmentsDir:n.join(t,"model-assignments"),modelEnvironmentsDir:n.join(t,"model-environments"),updatesDir:n.join(t,"updates"),logsDir:n.join(t,"logs")}}function Ei(e){t.mkdirSync(e,{recursive:!0})}function _i(e,t){Ei(n.dirname(e)),h.sync(e,`${JSON.stringify(t,null,2)}\n`,{encoding:"utf8"})}function Ti(e,t){console.warn(JSON.stringify({message:e,...t}))}function ki(e){return e&&"object"==typeof e&&"issues"in e?{issues:e.issues}:{error:e instanceof Error?e.message:String(e)}}function xi(e,n){const i=n.logger||Ti;let r;try{r=JSON.parse(t.readFileSync(e,"utf8"))}catch(t){return void i("stored JSON could not be read",{filePath:e,...ki(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 Ci(e){return`${e}_${m.randomUUID().replace(/-/g,"").slice(0,20)}`}function Oi(){return m.randomBytes(24).toString("base64url")}class Ri{directory;options;constructor(e,t={}){this.directory=e,this.options=t}init(){Ei(this.directory)}filePath(e){return n.join(this.directory,`${e}.json`)}list(){return this.init(),t.readdirSync(this.directory).filter(e=>e.endsWith(".json")).sort().flatMap(e=>{const t=xi(n.join(this.directory,e),this.options);return t?[t]:[]})}get(e){const n=this.filePath(e);return t.existsSync(n)?xi(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 _i(this.filePath(n.id),n),n}patch(e,t){const n=this.get(e);if(!n)return;const i={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:(new Date).toISOString()};return this.put(i)}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}}class Di{filePathValue;defaults;options;constructor(e,t,n={}){this.filePathValue=e,this.defaults=t,this.options=n}init(){Ei(n.dirname(this.filePathValue)),t.existsSync(this.filePathValue)||this.put(this.defaults())}get(){return this.init(),t.existsSync(this.filePathValue)?xi(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 _i(this.filePathValue,n),n}}class ji 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 Pi(e){return n.join(e,"owner.json")}function Mi(e){return n.join(e,"initializing.json")}function Li(e){return n.join(e,"recovering.json")}function $i(e){try{const n=JSON.parse(t.readFileSync(Pi(e),"utf8"));if(!Number.isInteger(n.pid)||Number(n.pid)<=0||"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}}function Fi(e){if(!Number.isInteger(e)||Number(e)<=0)return!1;try{return process.kill(Number(e),0),!0}catch(e){return"EPERM"===e.code}}function Ui(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=Vi(e);if(s?.token!==i.token)throw Hi(r),new Error(`Process lock initialization was superseded: ${e}`);t.renameSync(r,Pi(e)),Hi(Mi(e))}function Vi(e){try{return JSON.parse(t.readFileSync(Mi(e),"utf8"))}catch{return}}function Hi(e){try{t.unlinkSync(e)}catch(e){if("ENOENT"!==e.code)throw e}}function qi(){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}function Bi(e){try{const n=Vi(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 Ki(e,i){try{return t.writeFileSync(Li(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=Li(e),r=Gi(i),s=Date.parse(r?.startedAt||"");if(Fi(r?.pid)||Number.isFinite(s)&&Date.now()-s<2e3)return!1;const o=n.join(e,`.recovering-${m.randomUUID()}.stale`);try{t.renameSync(i,o)}catch(e){if(["ENOENT","EEXIST"].includes(e.code||""))return!1;throw e}const a=Gi(o);if(a?.token===r?.token)return Hi(o),!0;try{t.linkSync(o,i)}catch(e){if("EEXIST"!==e.code)throw e}finally{Hi(o)}return!1}(e)&&Ki(e,i);if("ENOENT"===r.code)return!1;throw r}}function Gi(e){try{return JSON.parse(t.readFileSync(e,"utf8"))}catch{return}}function Ji(e,t){return Gi(Li(e))?.token===t}function Wi(e,t=process.platform){const i=n.resolve(e),r=m.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 Yi="TASK_HANDOFF_NODE_AGENT_V1";function Xi(e=""){return m.createHash("sha256").update(e).digest("hex")}function Zi(e,t){return m.createHmac("sha256",e).update(function(e){return[Yi,e.keyId,e.method.toUpperCase(),e.pathWithQuery,e.timestamp,e.nonce,e.bodySha256].join("\n")}(t)).digest("hex")}function Qi(e){const t=e.timestamp||(new Date).toISOString(),n=e.nonce||m.randomBytes(18).toString("base64url"),i=Xi(e.body||""),r=Zi(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}}const er=new Set(["DELETE","GET","HEAD","PATCH","POST","PUT","OPTIONS"]);function tr(e){return"string"==typeof e&&er.has(e.toUpperCase())?e.toUpperCase():"GET"}function nr(){return(new Date).toISOString()}function ir(){return process.env.TASK_HANDOFF_NPM_COMMAND||"npm"}function rr(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n="string"==typeof t.updatedAt?t.updatedAt:nr(),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=lt.strip().safeParse(t.impact).success?lt.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}:ct.strip().safeParse(t.error).success?ct.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=ut.strip().safeParse(t.rollout);return{...g,source:"npm",status:c,impact:l,runtimeArtifacts:Array.isArray(t.runtimeArtifacts)?t.runtimeArtifacts.flatMap(e=>{const t=at.strip().safeParse(e);return t.success?[t.data]:[]}):[],rollout:f.success?f.data:h,...u?{error:u}:{},...r?{completedAt:t.completedAt||n}:{}}}class sr{records;constructor(e){this.records=new Ri(e.updatesDir,{schema:gt,sanitize:rr})}init(){this.records.init()}list(){return this.records.list().sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}create(e,t){const n=nr();return this.records.put(gt.parse({id:Ci("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(gt.parse({...n,...t,id:e,createdAt:n.createdAt,updatedAt:nr()}))}reconcileRollouts(e,t){const n=new Map(e.map(e=>[e.id,e]));for(const e of this.list().filter(e=>["updating-node","restarting-node","converging-instances"].includes(e.status))){const i="converging-instances"!==e.status&&t===e.toVersion?this.patch(e.id,{status:"converging-instances",rollout:{...e.rollout,phase:"converging-instances",nodeVersion:t}}):e;if("converging-instances"!==i.status)continue;const r=i.rollout.expectedInstanceIds,s=r.map(e=>n.get(e)),o=s.filter(e=>e?.ready&&"matched"===e.runtimeVersion?.phase&&e.runtimeVersion.actualVersion===i.toVersion).length,a=s.filter(e=>e&&["created","stopped","failed"].includes(e.status||"")&&"failed"!==e.runtimeVersion?.phase).length,c=s.filter(e=>!e||"failed"===e.runtimeVersion?.phase).length,d=Math.max(0,r.length-o-c-a),l=c>0?"degraded":0===d?"succeeded":"converging-instances";this.patch(i.id,{status:l,rollout:{...i.rollout,phase:l,nodeVersion:t,expectedInstanceCount:r.length,matchedInstanceCount:o,pendingInstanceCount:d,failedInstanceCount:c,deferredInstanceCount:i.impact.stoppedInstanceCount+a},..."succeeded"===l||"degraded"===l?{completedAt:nr()}:{}})}}run(e,t){(async()=>{this.patch(e.id,{status:"updating-node",rollout:{...e.rollout,phase:"updating-node"},startedAt:nr(),error:void 0});try{await t(e),this.patch(e.id,{status:"succeeded",completedAt:nr()})}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:nr()})}})()}}const or="runtime-manifest.json";class ar 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 cr(e,t=""){const i=[],r=await I.readdir(n.join(e,t),{withFileTypes:!0});for(const s of r){const r=t?n.posix.join(t,s.name):s.name;if(!t&&r===or)continue;const o=n.join(e,...r.split("/"));if(s.isDirectory()){i.push(...await cr(e,r));continue}if(s.isSymbolicLink()){const t=await I.readlink(o);if(n.isAbsolute(t))throw new ar("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 ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload symlink escapes the artifact: ${r}`);if(!await I.lstat(s).catch(()=>{}))throw new ar("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 ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime payload contains unsupported entry: ${r}`);const a=await I.lstat(o);i.push({absolutePath:o,relativePath:r,kind:"file",size:a.size})}return i}async function dr(e){const n=(await cr(e)).sort((e,t)=>function(e,t){return Buffer.compare(Buffer.from(e,"utf8"),Buffer.from(t,"utf8"))}(e.relativePath,t.relativePath)),i=m.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 lr(e){for(const[t,n]of[["version",e.version],["platform",e.platform],["arch",e.arch]])if(!/^[0-9A-Za-z._-]+$/.test(n))throw new ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Invalid runtime artifact ${t}: ${n}`);return`${e.version}-${e.platform}-${e.arch}`}function ur(e,t){return`${lr(e)}-${e.sha256}-${t}`}async function mr(e){const n=m.createHash("sha256");for await(const i of t.createReadStream(e))n.update(i);return n.digest("hex")}class pr{#e;#t;#n=new Map;constructor(e){this.#e=e.cacheDir,this.#t=e.fetchImpl??fetch}resolve(e,t){const n=at.parse(e);if(!/^[a-f0-9]{64}$/.test(t.archiveSha256))throw new ar("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");if((t.archiveUrl?1:0)+(t.archivePath?1:0)!=1)throw new ar("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact source must specify exactly one archive location.");const i=ur(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 ar("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime archive SHA-256 is invalid.");const r=ur(e,i.archiveSha256),s=n.join(this.#e,"archives"),o=n.join(s,`${r}.tar.gz`);if(await I.mkdir(s,{recursive:!0}),await this.#r(o,e,i.archiveSha256))return{identity:e,archivePath:o,cacheHit:!0};await I.rm(o,{force:!0});const a=n.join(s,`.${r}.${m.randomUUID()}.part`);try{const n=await I.open(a,"wx");if(i.archivePath)await y.pipeline(t.createReadStream(i.archivePath),n.createWriteStream());else{const e=await this.#t(i.archiveUrl);if(!e.ok||!e.body)throw await n.close(),new ar("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Runtime artifact download failed with HTTP ${e.status}.`,{retryable:e.status>=500});await y.pipeline(e.body,n.createWriteStream())}if(await mr(a)!==i.archiveSha256)throw new ar("INSTANCE_RUNTIME_ARTIFACT_INVALID","Downloaded runtime archive SHA-256 does not match release metadata.");return await this.#s(a,e),await I.rename(a,o),{identity:e,archivePath:o,cacheHit:!1}}catch(e){if(e instanceof ar)throw e;throw new ar("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE","Could not download runtime artifact.",{cause:e,retryable:!0})}finally{await I.rm(a,{force:!0})}}async#r(e,t,n){try{return await mr(e)===n&&(await this.#s(e,t),!0)}catch{return!1}}async#s(e,t){const i=n.join(this.#e,"validation",`${lr(t)}-${m.randomUUID()}`);try{await async function(e,t){await I.mkdir(t,{recursive:!0});try{await A.extract({file:e,cwd:t,strict:!0,preservePaths:!1,filter:(e,t)=>{const i=n.posix.normalize(e.replace(/^\.\//,""));if(!i||".."===i||i.startsWith("../")||n.posix.isAbsolute(i))throw new ar("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 ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime archive contains unsupported entry type ${r??"unknown"}: ${e}`);return!0}})}catch(e){throw new ar("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 I.readFile(n.join(e,or),"utf8"))}catch(e){throw new ar("INSTANCE_RUNTIME_ARTIFACT_INVALID","Runtime artifact manifest is missing or invalid JSON.",{cause:e})}const i=at.safeParse(t);if(!i.success)throw new ar("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 ar("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 ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Unsupported runtime artifact format ${r.formatVersion}.`);if(i?.platform&&"universal"!==r.platform&&r.platform!==i.platform)throw new ar("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 ar("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 ar("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 ar("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 ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`${t} escapes the runtime root.`);return i}(r.entrypoint,"Runtime entrypoint"),o=await I.lstat(n.join(e,...s.split("/"))).catch(()=>{});if(!o?.isFile())throw new ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Runtime entrypoint is missing: ${s}`);const a=await dr(e);if(a!==r.sha256)throw new ar("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 I.rm(i,{recursive:!0,force:!0})}}}async function gr(e,t,i,r=fetch){if("linux"!==t||!["x64","arm64"].includes(i))throw new ar("INSTANCE_BASE_RUNTIME_INCOMPATIBLE",`Managed controlled-instance updates require a Linux x64 or arm64 target, received ${t}/${i}.`);const s=await async function(e){const t=`controlled-instance-runtime-${e}-linux-universal`,i=function(){const e=process.env.TASK_HANDOFF_BUNDLED_RUNTIME_DIR?.trim();return n.resolve(e||n.join(n.dirname(process.argv[1]||process.cwd()),"..","runtime-artifacts"))}();try{const[r,s]=await Promise.all([I.readFile(n.join(i,`${t}.manifest.json`),"utf8"),I.readFile(n.join(i,`${t}.tar.gz.sha256`),"utf8")]),o=at.safeParse(JSON.parse(r));if(!o.success||o.data.version!==e||"linux"!==o.data.platform||"universal"!==o.data.arch)throw new ar("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 ar("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 ar)throw t;throw new ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Could not read bundled controlled-instance ${e}.`,{cause:t})}}(e);if(s)return s;const o=`controlled-instance-runtime-${e}-linux-universal`,a=function(e){const t=process.env.TASK_HANDOFF_RUNTIME_RELEASE_BASE_URL?.trim();return t?t.replaceAll("{version}",e).replace(/\/$/,""):`https://github.com/edgestorage/task-handoff/releases/download/v${e}`}(e),c=`${a}/${o}.manifest.json`,d=`${a}/${o}.tar.gz`,l=`${a}/${o}.tar.gz.sha256`,[u,m]=await Promise.all([r(c),r(l)]).catch(t=>{throw new ar("INSTANCE_RUNTIME_ARTIFACT_UNAVAILABLE",`Could not read release metadata for controlled-instance ${e}.`,{cause:t,retryable:!0})});if(!u.ok||!m.ok)throw new ar("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 ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release manifest for controlled-instance ${e} is not valid JSON.`,{cause:t})}const g=at.safeParse(p);if(!g.success)throw new ar("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 ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release identity mismatch: requested ${e}-linux-universal, received ${g.data.version}-${g.data.platform}-${g.data.arch}.`);const h=(await m.text()).trim().split(/\s+/)[0]?.toLowerCase();if(!h||!/^[a-f0-9]{64}$/.test(h))throw new ar("INSTANCE_RUNTIME_ARTIFACT_INVALID",`Release checksum for controlled-instance ${e} is invalid.`);return{identity:g.data,source:{archiveUrl:d,archiveSha256:h}}}class hr{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=Nr(i.retryBaseDelayMs??1e3,"retryBaseDelayMs"),this.retryMaxDelayMs=Nr(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=fr(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()},!yr(n)&&"failed"!==n.health);if(n.runtimeVersion?.desiredVersion===i&&(n.runtimeVersion?.attempt||0)>=this.maxAttempts)return"failed"===n.runtimeVersion?.phase&&n.runtimeVersion.error?n:this.storePermanentFailure(n,i,zr(i,r,this.maxAttempts,n.runtimeVersion?.error));if(n=this.storeState(n,function(e,t,n,i=!1){const r=e.runtimeVersion;return{desiredVersion:t,...n?{actualVersion:n}:{},phase:"pending",attempt:r?.desiredVersion===t&&"matched"!==r.phase?r.attempt:0,error:n!==t||i?Ar(t,n):br("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Controlled-instance ${t} is running, but the active runtime artifact does not match the desired release identity.`,t,n,!0)}}(n,i,r,s),!1),yr(n)&&!t.startRequested)return n;for(;(n.runtimeVersion?.attempt||0)<this.maxAttempts;){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");let r,s=!1;try{if(Ir(n)){n=this.storePhase(n,"draining");const t=await this.waitUntil(e,this.drainTimeoutMs,e=>!Ir(e));if(n=this.requireInstance(e),!t){if(this.cancelled.has(e))return this.storePhase(n,"pending");await(this.hooks.onForcedDrain?.(n))}}if(n=this.storePhase(this.requireInstance(e),"installing",!0),await this.hooks.install(n,i),s=!0,this.cancelled.has(e)||yr(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=>fr(e)===i);if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(!r)throw br("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} did not register controlled-instance ${i} after restart.`,i,fr(this.requireInstance(e)),!0);const o=this.requireInstance(e);if(this.hooks.isInstalled&&!await this.hooks.isInstalled(o,i))throw br("INSTANCE_RUNTIME_VERIFICATION_FAILED",`Instance ${e} reported controlled-instance ${i}, but its active runtime release is missing.`,i,fr(o),!0);return this.storeState(o,{desiredVersion:i,actualVersion:i,phase:"matched",attempt:o.runtimeVersion?.attempt||1,matchedAt:this.timestamp()},!yr(o)&&"failed"!==o.health)}catch(t){if(this.cancelled.has(e))return this.storePhase(this.requireInstance(e),"pending");if(r=wr(t,i,fr(this.store.get(e))),s&&this.hooks.rollback)try{await this.hooks.rollback(this.requireInstance(e))}catch(e){r.message=`${r.message} Rollback failed: ${e instanceof Error?e.message:String(e)}`,r.retryable=!1}}n=this.requireInstance(e);const o=n.runtimeVersion?.attempt||1;if(!r.retryable||o>=this.maxAttempts)return this.storePermanentFailure(n,i,o>=this.maxAttempts&&r.retryable?zr(i,fr(n),this.maxAttempts,r):r);n=this.storeState(n,{desiredVersion:i,...fr(n)?{actualVersion:fr(n)}:{},phase:"pending",attempt:o,lastAttemptAt:this.timestamp(),error:r},!1),await this.delay(this.retryDelayMs(o))}return this.storePermanentFailure(n,i,zr(i,fr(n),this.maxAttempts,n.runtimeVersion?.error))}storePermanentFailure(e,t,n){const i=fr(e);return this.storeState(e,{desiredVersion:t,...i?{actualVersion:i}:{},phase:"failed",attempt:e.runtimeVersion?.attempt||0,lastAttemptAt:this.timestamp(),error:{...n,retryable:!1}},!1)}retryDelayMs(e){return Math.min(this.retryMaxDelayMs,this.retryBaseDelayMs*2**Math.max(0,e-1))}storePhase(e,t,n=!1){const i=this.desiredVersion(),r=fr(e);return this.storeState(e,{desiredVersion:i,...r?{actualVersion:r}:{},phase:t,attempt:(e.runtimeVersion?.attempt||0)+(n?1:0),lastAttemptAt:this.timestamp(),..."pending"===t?{error:Ar(i,r)}:{}},!1)}storeState(e,t,n){const i=this.store.get(e.id)||e;return this.store.put(pn.parse({...i,runtimeVersion:t,ready:n,...n?{}:{health:"failed"===i.health?"failed":"degraded"},updatedAt:this.timestamp()}))}async waitUntil(e,t,n){const i=this.now().getTime()+t;for(;;){const t=this.store.get(e);if(t&&n(t))return!0;if(this.cancelled.has(e))return!1;if(this.now().getTime()>=i)return!1;await this.delay(Math.min(this.pollIntervalMs,Math.max(0,i-this.now().getTime())))}}requireInstance(e){const t=this.store.get(e);if(!t)throw new Error(`Instance ${e} was removed during runtime reconciliation.`);return t}timestamp(){return this.now().toISOString()}}function fr(e){return e?.build?.packageVersion||e?.instanceVersion}function Ir(e){return e.apps.runningCount>0||e.aiSessions.runningCount>0}function yr(e){return["created","stopped","failed"].includes(e.status)}function Ar(e,t){return br("INSTANCE_RUNTIME_VERSION_MISMATCH",`Expected controlled-instance ${e}, received ${t||"an unknown version"}.`,e,t,!0)}function br(e,t,n,i,r){return{code:e,message:t,expectedVersion:n,...i?{actualVersion:i}:{},retryable:r}}function wr(e,t,n){if(e&&"object"==typeof e&&"code"in e&&"message"in e){const i=e;return br(i.code,i.message,t,n,i.retryable??!0)}return br("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 br(i?.code||"INSTANCE_RUNTIME_INSTALL_FAILED",`Runtime convergence exhausted ${n} attempts.${r}`,e,t,!1)}function Nr(e,t){if(!Number.isFinite(e)||e<0)throw new TypeError(`${t} must be a nonnegative finite number.`);return e}const vr=u.z.record(u.z.string(),u.z.string()),Sr=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 Er{directory;constructor(e){this.directory=e}get(e){try{return vr.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=vr.parse(n);t.mkdirSync(this.directory,{recursive:!0,mode:448});const r=this.filePath(e);return h.sync(r,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(r,384),i}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class _r{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=St.parse(e);this.init();const i=this.filePath(n.id);return h.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){const n=this.filePath(e);return!!t.existsSync(n)&&(t.unlinkSync(n),!0)}read(e){try{const i=JSON.parse(t.readFileSync(e,"utf8")),r=n.basename(e,".json"),s=St.safeParse(i);if(s.success&&s.data.id===r&&Pt(s.data)===s.data.id)return s.data;const o=St.strip().safeParse(i);return o.success&&o.data.id===r&&Pt(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 Tr{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=Tt.safeParse(i);if(r.success)return r.data;const s=Tt.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=Tt.parse(e);this.init();const i=this.filePath(n.instanceId);return h.sync(i,`${JSON.stringify(n,null,2)}\n`,{encoding:"utf8",mode:384}),t.chmodSync(i,384),n}delete(e){t.rmSync(this.filePath(e),{force:!0})}filePath(e){return n.join(this.directory,`${e}.json`)}}class kr{usedNonces=new Map;identity;nodeId;overrideSecret;overrideKeyId;nowMs;constructor(e,t,n,i,r=Date.now){this.identity=e,this.nodeId=t,this.overrideSecret=n,this.overrideKeyId=i,this.nowMs=r}hasRemoteSecrets(){return this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId).length>0}verify(e){const t=function(e){const t=new Map;for(const[n,i]of Object.entries(e)){const e=Array.isArray(i)?i.join(","):"string"==typeof i?i:void 0===i?"":String(i);t.set(n.toLowerCase(),e)}return{nodeId:t.get("x-taskhandoff-node-id")||"",keyId:t.get("x-taskhandoff-key-id")||"",timestamp:t.get("x-taskhandoff-timestamp")||"",nonce:t.get("x-taskhandoff-nonce")||"",bodySha256:t.get("x-taskhandoff-body-sha256")||"",signature:t.get("x-taskhandoff-signature")||""}}(e.headers);if(!t.nodeId&&!t.signature)return!1;const n=this.identity.remoteSecrets(this.overrideSecret,this.overrideKeyId);if(!n.length)return!1;if(t.nodeId!==this.nodeId)throw Object.assign(new Error("Invalid node agent HMAC node id."),{statusCode:401,code:"NODE_AGENT_HMAC_NODE_MISMATCH"});if(!t.keyId)throw Object.assign(new Error("Node agent HMAC key id is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_MISSING"});const i=n.filter(e=>t.keyId===e.keyId);if(!i.length)throw Object.assign(new Error("Invalid node agent HMAC key id."),{statusCode:401,code:"NODE_AGENT_HMAC_KEY_INVALID"});const r=Date.parse(t.timestamp);if(!Number.isFinite(r)||Math.abs(this.nowMs()-r)>6e4)throw Object.assign(new Error("Node agent HMAC timestamp is outside the allowed window."),{statusCode:401,code:"NODE_AGENT_HMAC_TIMESTAMP_INVALID"});if(!t.nonce)throw Object.assign(new Error("Node agent HMAC nonce is missing."),{statusCode:401,code:"NODE_AGENT_HMAC_NONCE_MISSING"});this.pruneNonces();const 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 o=Xi(null==(a=e.body)?"":"string"==typeof a||Buffer.isBuffer(a)?a:JSON.stringify(a));var a;if(t.bodySha256!==o)throw Object.assign(new Error("Node agent HMAC body hash mismatch."),{statusCode:401,code:"NODE_AGENT_HMAC_BODY_HASH_INVALID"});if(!i.some(n=>function(e,t){const n=Buffer.from(e,"hex"),i=Buffer.from(t,"hex");return n.length===i.length&&m.timingSafeEqual(n,i)}(t.signature,Zi(n.secret,{keyId:t.keyId,method:e.method,pathWithQuery:e.url,timestamp:t.timestamp,nonce:t.nonce,bodySha256:o}))))throw Object.assign(new Error("Invalid node agent HMAC signature."),{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_INVALID"});return this.usedNonces.set(s,r+6e4+1),t.keyId}pruneNonces(){const e=this.nowMs();for(const[t,n]of this.usedNonces)n<=e&&this.usedNonces.delete(t)}}const xr=u.z.string().trim().min(1).max(160),Cr=u.z.string().datetime(),Or=u.z.string().min(1).max(4096),Rr=u.z.string().trim().url().max(2048),Dr=u.z.object({tokenHash:u.z.string().trim().min(1).max(256),expiresAt:Cr,createdAt:Cr,controlPlaneName:u.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:Rr.optional()}).strip(),jr=u.z.object({id:xr,keyId:xr,name:u.z.string().trim().min(1).max(160).optional(),url:Rr.optional(),secret:Or,pairedAt:Cr,updatedAt:Cr,active:u.z.boolean().default(!0)}).strip(),Pr=u.z.object({controlPlaneName:u.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:u.z.string().trim().max(2048).optional(),expiresInMs:u.z.number().int().positive().max(36e5).optional()}).strict(),Mr=u.z.object({joinToken:u.z.string().trim().min(1).max(4096),controlPlaneId:u.z.string().trim().min(1).max(160).optional(),controlPlaneName:u.z.string().trim().min(1).max(160).optional(),controlPlaneUrl:u.z.string().trim().max(2048).optional()}).strict(),Lr=u.z.object({controlPlaneUrl:u.z.string().trim().url().max(2048),joinToken:u.z.string().trim().min(1).max(4096),controlPlaneName:u.z.string().trim().min(1).max(160).optional(),activate:u.z.boolean().optional()}).strict();function $r(){return(new Date).toISOString()}const Fr=new Set(["nodeId","createdAt","updatedAt","pairingInvites","remoteControlPlanes"]),Ur=new Set(["tokenHash","expiresAt","createdAt","controlPlaneName","controlPlaneUrl"]),Vr=new Set(["id","keyId","name","url","secret","pairedAt","updatedAt","active"]);function Hr(e,t){console.warn(JSON.stringify({message:e,...t}))}function qr(e,t){return Object.assign(new Error(e,void 0===t?void 0:{cause:t}),{code:"NODE_AGENT_IDENTITY_INVALID"})}function Br(e,t){return Object.keys(e).filter(e=>!t.has(e))}function Kr(e,t,n){const i=Cr.safeParse(e);return i.success?i.data:(n("invalid node agent identity timestamp was replaced",{field:t}),$r())}function Gr(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw qr("Node agent identity must be a JSON object.");const n=e,i=xr.safeParse(n.nodeId);if(!i.success)throw qr("Node agent identity has an invalid nodeId.",i.error);const r=i.data,s=Br(n,Fr);return s.length&&t("unknown node agent identity fields were ignored",{fields:s}),{nodeId:r,createdAt:Kr(n.createdAt,"createdAt",t),updatedAt:Kr(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=Br(e,Ur);n.length&&t("unknown node agent pairing invite fields were ignored",{fields:n});const i=Dr.safeParse(e);return i.success?[i.data]:(t("invalid node agent pairing invite was ignored",{issues:i.error.issues}),[])}):[],remoteControlPlanes:Array.isArray(n.remoteControlPlanes)?n.remoteControlPlanes.flatMap(e=>{if(!e||"object"!=typeof e||Array.isArray(e))return t("invalid node agent remote control-plane was ignored",{}),[];const n=Br(e,Vr);n.length&&t("unknown node agent remote control-plane fields were ignored",{fields:n});const i=jr.safeParse(e);return i.success?[i.data]:(t("invalid node agent remote control-plane was ignored",{issues:i.error.issues}),[])}):[]}}class Jr{paths;logger;constructor(e,t={}){this.paths=e,this.logger=t.logger||Hr}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 qr(`Node agent identity contains invalid JSON: ${this.paths.identityPath}`,e)}return Gr(n,this.logger)}write(e){t.mkdirSync(n.dirname(this.paths.identityPath),{recursive:!0});const i=Gr({...e,updatedAt:$r()},this.logger);h.sync(this.paths.identityPath,`${JSON.stringify(i,null,2)}\n`,{encoding:"utf8",mode:384})}}function Wr(){return(new Date).toISOString()}class Yr{store;constructor(e){this.store=new Jr(e)}resolveNodeId(e){if(e?.trim())return this.writeNodeId(e.trim()),e.trim();const t=this.store.read();if(t?.nodeId)return t.nodeId;const n=Ci("node");return this.writeNodeId(n),n}createPairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=Wr(),i=new Date(Date.now()+(e.expiresInMs||6e5)).toISOString(),r=Oi(),s={tokenHash:Xi(r),createdAt:n,expiresAt:i,...e.controlPlaneName?{controlPlaneName:e.controlPlaneName}:{},...e.controlPlaneUrl?{controlPlaneUrl:e.controlPlaneUrl}:{}};return this.store.write({...t,pairingInvites:[...t.pairingInvites||[],s]}),{...s,token:r}}completePairingInvite(e){const t=this.prunePairingInvites(this.store.read()||this.newIdentity()),n=Xi(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=Wr(),s={id:e.controlPlaneId||Ci("cp"),keyId:Ci("key"),...e.controlPlaneName||i.controlPlaneName?{name:e.controlPlaneName||i.controlPlaneName}:{},...e.controlPlaneUrl||i.controlPlaneUrl?{url:e.controlPlaneUrl||i.controlPlaneUrl}:{},secret:Oi(),pairedAt:r,updatedAt:r,active:!0};return this.store.write({...t,pairingInvites:(t.pairingInvites||[]).filter(e=>e.tokenHash!==n),remoteControlPlanes:[...(t.remoteControlPlanes||[]).filter(e=>e.id!==s.id),s]}),s}upsertRemoteControlPlane(e){const t=this.store.read()||this.newIdentity(),n=e.url?.replace(/\/$/,"");return this.store.write({...t,remoteControlPlanes:[...(t.remoteControlPlanes||[]).filter(t=>t.id!==e.id&&(!n||t.url?.replace(/\/$/,"")!==n)),e]}),e}createRemoteControlPlane(e){const t=Wr();return{id:Ci("cp"),keyId:Ci("key"),...e.name?{name:e.name}:{},url:e.url,secret:Oi(),pairedAt:t,updatedAt:t,active:!1!==e.active}}configuredRemoteControlPlanes(){return this.store.read()?.remoteControlPlanes||[]}listRemoteControlPlanes(e=""){return(this.store.read()?.remoteControlPlanes||[]).map(({secret:t,...n})=>({...n,current:Boolean(e&&n.keyId===e)})).sort((e,t)=>Number(t.current)-Number(e.current)||t.updatedAt.localeCompare(e.updatedAt))}deleteRemoteControlPlane(e,t=""){if(t&&e===t){const e=new Error("Cannot delete the key currently used by this control-plane connection.");throw Object.assign(e,{statusCode:409,code:"NODE_AGENT_REMOTE_KEY_IN_USE"}),e}const n=this.store.read();if(!n)return!1;const i=(n.remoteControlPlanes||[]).filter(t=>t.keyId!==e);return i.length!==(n.remoteControlPlanes||[]).length&&(this.store.write({...n,remoteControlPlanes:i}),!0)}remoteSecrets(e,t){return[...(this.store.read()?.remoteControlPlanes||[]).map(e=>({keyId:e.keyId,secret:e.secret})),...e&&t?[{keyId:t,secret:e}]:[]]}reverseTunnelSecret(e,t,n){if(t&&n)return{keyId:n,secret:t};const i=this.store.read()?.remoteControlPlanes||[];if(!i.length)return;if(e){const t=e.replace(/\/$/,""),n=i.find(e=>e.url?.replace(/\/$/,"")===t);if(n)return{keyId:n.keyId,secret:n.secret}}const r=[...i].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))[0];return r?{keyId:r.keyId,secret:r.secret}:void 0}newIdentity(){return{nodeId:this.resolveNodeId(),createdAt:Wr(),updatedAt:Wr(),pairingInvites:[],remoteControlPlanes:[]}}writeNodeId(e){const t=this.store.read();this.store.write({...t||{createdAt:Wr()},nodeId:e,updatedAt:Wr(),pairingInvites:t?.pairingInvites||[],remoteControlPlanes:t?.remoteControlPlanes||[]})}prunePairingInvites(e){const t=Date.now();return{...e,pairingInvites:(e.pairingInvites||[]).filter(e=>Date.parse(e.expiresAt)>t)}}}const Xr=new Set(["content-encoding","content-length","transfer-encoding"]),Zr=["codex","claude"],Qr=5e3,es="runtime_local_host",ts="task-handoff.node-agent.builtin",ns=new Set(["linux","darwin","win32","freebsd","openbsd","aix","sunos"]);function is(e){return ns.has(e)?e:"unknown"}function rs(e){const t={...e};return delete t[ts],t}const ss=u.z.object({version:u.z.literal(1),externalListener:sn}).strict(),os=u.z.object({}).strict().default({}),as=ht.strict();function cs(e){const t=process.env[e]?.trim();return t||void 0}function ds(){try{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(s.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,"..","package.json"),n.resolve(e,"..","..","package.json")].find(e=>t.existsSync(e));return i&&JSON.parse(t.readFileSync(i,"utf8")).version||"unknown"}catch{return"unknown"}}function ls(e){const t=ds();return e===t?{desiredVersion:t,actualVersion:e,phase:"matched",attempt:0,matchedAt:As()}:{desiredVersion:t,...e?{actualVersion:e}:{},phase:"pending",attempt:0,error:{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${t}, received ${e||"an unknown version"}.`,expectedVersion:t,...e?{actualVersion:e}:{},retryable:!0}}}function us(e,t,n=!0){if(!n)return ls(t);const i=ds(),r=e.runtimeVersion;return r&&r.desiredVersion===i?dt.parse({...r,desiredVersion:i,...t?{actualVersion:t}:{actualVersion:void 0},..."pending"===r.phase&&t!==i?{error:{code:"INSTANCE_RUNTIME_VERSION_MISMATCH",message:`Expected controlled-instance ${i}, received ${t||"an unknown version"}.`,expectedVersion:i,...t?{actualVersion:t}:{},retryable:!0}}:"pending"===r.phase?{error:void 0}:{}}):ls(t)}function ms(e){return Object.fromEntries([...e.entries()].filter(([e])=>!Xr.has(e.toLowerCase())))}function ps(e){return e.bodyBase64?Buffer.from(e.bodyBase64,"base64"):e.body}const gs=67108864;function hs(){const e=Number(process.env.TASK_HANDOFF_INSTANCE_PROXY_MAX_RESPONSE_BYTES);return Number.isSafeInteger(e)&&e>0?e:67108864}function fs(e){const t=e.authorization;return"string"==typeof t&&t.startsWith("Bearer ")?t.slice(7).trim():void 0}function Is(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 ys(e){return!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}function As(){return(new Date).toISOString()}function bs(e){return"all-ipv4"===e?"0.0.0.0":"127.0.0.1"}function ws(e){if(!e||"object"!=typeof e||Array.isArray(e))return e;const t=e,n=t.externalListener&&"object"==typeof t.externalListener&&!Array.isArray(t.externalListener)?t.externalListener:{},i=Object.keys(t).filter(e=>"version"!==e&&"externalListener"!==e),r=Object.keys(n).filter(e=>"bindScope"!==e&&"port"!==e);return(i.length||r.length)&&console.warn(JSON.stringify({message:"unknown stored node agent runtime setting fields were ignored",filePath:"runtime-settings.json",fields:[...i,...r.map(e=>`externalListener.${e}`)]})),{version:t.version,externalListener:{bindScope:n.bindScope,port:n.port}}}function zs(e){return"local-folder"===e.type?wt.parse({mode:"local-bind",path:"/workspace",readOnly:!1}):wt.parse({mode:"git-clone",path:"/workspace",readOnly:!1})}function Ns(e){const t=bt.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 Nt.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:zs(t),labels:{},createdAt:e.createdAt,updatedAt:e.updatedAt})}async function vs(e,t){if(!t.target.web)return"unknown";const n=new AbortController,i=setTimeout(()=>n.abort(),2e3);try{return(await e(`${Ts(t)}/api/health`,{signal:n.signal})).ok?"reachable":"endpoint-unreachable"}catch{return"endpoint-unreachable"}finally{clearTimeout(i)}}async function Ss(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 Es(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=Ts(t),s=Number(process.env.TASK_HANDOFF_CONFIG_AUTO_IMPORT_TIMEOUT_MS||Qr);for(const o of Zr)try{const a=await Ss(e,`${r}/api/config-sync/import/${encodeURIComponent(o)}`,{method:"POST"},Number.isFinite(s)&&s>0?s:Qr);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 _s(e,t,n){const i=t.requireInstance(n);if("reachable"!==i.targetStatus||!i.target.web)return!1;const r=await Ss(e,`${Ts(i)}/api/internal/model-environment`,{method:"PUT",headers:{"content-type":"application/json",authorization:`Bearer ${i.registrationToken}`},body:JSON.stringify(t.resolvedAssignedModelEnvironment(n))},Qr);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 Ts(e){const t=e.target.web;if(!t){const t=new Error(`Instance ${e.id} does not have a web endpoint.`);throw Object.assign(t,{statusCode:409,code:"NODE_INSTANCE_WEB_ENDPOINT_MISSING"}),t}if("direct-port"!==e.target.strategy)return t.replace(/\/$/,"");try{const e=new URL(t);return e.port?(e.hostname=process.env.TASK_HANDOFF_NODE_AGENT_PROXY_HOST||"127.0.0.1",e.toString().replace(/\/$/,"")):t.replace(/\/$/,"")}catch{return t.replace(/\/$/,"")}}function ks(e,t){const n=new Error(t);throw Object.assign(n,{statusCode:403,code:e}),n}function xs(e,t){e!==be&&console.warn(JSON.stringify({message:"protocol version mismatch",peer:t,expectedProtocolVersion:be,actualProtocolVersion:e||"missing",errorCode:"PROTOCOL_VERSION_MISMATCH"}))}function Cs(e){return"none"!==e.capabilities.artifactKind}function Os(e={}){return{...e,requiresImage:!1,supportsControlledInstanceApi:!0,supportsContainerLifecycle:!1,supportsAppSessions:!0,supportsHostSessions:!0,artifactKind:"none",isolation:"none"}}function Rs(e){return new Promise(t=>{const n=r.createServer();n.once("error",()=>t(!1)),n.listen({host:"127.0.0.1",port:e},()=>{n.close(()=>t(!0))})})}function Ds(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()})})}async function js(e,t){const n=t.get(e.id);if(n&&!n.killed)return n.kill("SIGTERM"),t.delete(e.id),void await Ds(n);if(e.runtime.pid){try{process.kill(e.runtime.pid,"SIGTERM")}catch{return}const t=Date.now()+3e3;for(;Date.now()<t;){try{process.kill(e.runtime.pid,0)}catch{return}await new Promise(e=>setTimeout(e,50))}try{process.kill(e.runtime.pid,"SIGKILL")}catch{}}}const Ps=new Set(["provisioning","starting","registering","registered","running"]);async function Ms(e,t){try{const n=await e(t,["--version"]);return{available:!0,command:t,version:(n.stdout||n.stderr).split(/\r?\n/)[0]?.trim()||void 0}}catch{return{available:!1}}}function Ls(e){return!0===e.managedArtifacts}class $s{managedArtifacts=!0;executor;platform;arch;runCommand;constructor(e,t,n,i){this.executor=e,this.runCommand=t,this.platform=n,this.arch=i}artifactTarget(e){return this.executor.inspectRuntimeTarget(e?.instance.runtime.containerName)}async installRuntime(e,t){const n=e.instance.runtime.containerName;if(!n)throw Object.assign(new Error(`Instance ${e.instance.id} does not have a Docker container.`),{code:"INSTANCE_RUNTIME_INSTALL_FAILED"});await this.executor.installRuntimeLauncher(n),await this.executor.installRuntimeRelease({containerName:n,expectedContainerId:e.instance.runtime.containerId,artifactPath:t.archivePath,identity:t.identity})}async inspectRuntime(e,t){const n=e.instance.runtime.containerName;return!!n&&function(e,t){return e.packageName===t.packageName&&e.version===t.version&&e.platform===t.platform&&e.arch===t.arch&&e.formatVersion===t.formatVersion&&e.launcherAbi===t.launcherAbi&&e.entrypoint===t.entrypoint&&e.sha256===t.sha256}(await this.executor.inspectRuntimeVersion(n),t)}async rollbackRuntime(e,t){const n=e.instance.runtime.containerName;n&&await this.executor.rollbackRuntime(n)}start(e){return this.executor.start(e)}stop(e){return this.executor.stop(e)}restart(e){return this.executor.restart(e,e.instance.runtime.containerId)}delete(e){return this.executor.delete(e)}async check(e){try{const t=(await this.runCommand("docker",["version","--format","{{.Server.Version}}"],{timeoutMs:5e3})).stdout.trim();return{status:"online",capabilities:{...e.capabilities,daemon:{status:"online",hostPlatform:is(this.platform),...t?{serverVersion:t}:{}}}}}catch(t){return{status:"offline",capabilities:{...e.capabilities,daemon:{status:"offline",hostPlatform:is(this.platform),error:t instanceof Error?t.message:String(t)}}}}}}class Fs{runCommand;paths;nodeAgentUrl;processByInstanceId=new Map;commandOverride;constructor(e,t,n,i){this.runCommand=e,this.paths=t,this.nodeAgentUrl=n,this.commandOverride=i}async start(e){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 Rs(e))return e;const n=new Error(`No free localhost port found in range ${t}-${Math.min(t+999,65535)}.`);throw Object.assign(n,{statusCode:503,code:"LOCAL_INSTANCE_PORT_UNAVAILABLE"}),n}(),s=n.join(this.paths.dataDir,"local-instances",e.instance.id),a=n.join(s,"logs");t.mkdirSync(a,{recursive:!0});const[c,...d]=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),l=[...d,"--host","127.0.0.1","--port",String(r)],u=t.openSync(n.join(a,"controlled-instance.out.log"),"a"),m=t.openSync(n.join(a,"controlled-instance.err.log"),"a"),p=o.spawn(c,l,{cwd:i,detached:!1,stdio:["ignore",u,m],env:{...process.env,TASK_HANDOFF_CONTROL_MODE:"controlled",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_WORKSPACE:i,TASK_HANDOFF_WORKSPACE_MODE:"local-bind",TASK_HANDOFF_DATA_DIR:s,TASK_HANDOFF_LOG_DIR:a,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(u),t.closeSync(m);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)})}(p)}catch(e){const r=e instanceof Error?e.message:String(e);try{t.appendFileSync(n.join(a,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] spawn failed command=${c} cwd=${i} error=${r}\n`)}catch{}throw Object.assign(new Error(`Controlled instance process could not start with command ${c} in ${i}: ${r}`),{statusCode:500,code:"LOCAL_INSTANCE_PROCESS_SPAWN_FAILED"})}this.processByInstanceId.set(e.instance.id,p),p.on("error",e=>{try{t.appendFileSync(n.join(a,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] process error pid=${p.pid??""} error=${e.message}\n`)}catch{}}),p.once("exit",(i,r)=>{this.processByInstanceId.delete(e.instance.id);try{t.appendFileSync(n.join(a,"controlled-instance.lifecycle.log"),`[${(new Date).toISOString()}] exited pid=${p.pid??""} code=${i??""} signal=${r??""}\n`)}catch{}});const g=`http://127.0.0.1:${r}`;return await async function(e,t=3e3){const n=Date.now()+t;for(;Date.now()<n;){try{if((await fetch(`${e}/api/health`)).ok)return!0}catch{}await new Promise(e=>setTimeout(e,100))}return!1}(g),{status:"registering",health:"unknown",connectionStatus:"online",agentStatus:"unknown",targetStatus:"unknown",uiAccessStatus:"unknown",target:{strategy:"direct-port",status:"unknown",web:g,api:`${g}/api`},workspace:{mode:"local-bind",status:"pending",path:i},runtime:{kind:"local",workspacePath:i,pid:p.pid,port:r,labels:{...e.instance.runtime.labels,"task-handoff.runtime-kind":"local"}}}}async stop(e){return await js(e.instance,this.processByInstanceId),{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 js(e.instance,this.processByInstanceId),this.start(e)}async delete(e){return this.stop(e)}async check(e){const[t,n]=await Promise.all([Ms(this.runCommand,"codex"),Ms(this.runCommand,"claude")]);return{status:"online",capabilities:Os({...e.capabilities,apps:{terminal:!0,codex:t,claude:n}})}}async stopAll(){const e=Array.from(this.processByInstanceId.values());for(const e of this.processByInstanceId.values())e.killed||e.kill("SIGTERM");this.processByInstanceId.clear(),await Promise.all(e.map(e=>Ds(e)))}}class Us{docker;local;constructor(e,t){this.docker=e,this.local=t}forRuntime(e){if("docker"===e.type)return this.docker;if("local"===e.type)return this.local;const t=new Error(`Runtime type ${e.type} is not supported by this node agent.`);throw Object.assign(t,{statusCode:400,code:"NODE_RUNTIME_TYPE_UNSUPPORTED"}),t}managedAdapters(){return[this.docker,this.local].filter(Ls)}async stopAll(){this.local instanceof Fs&&await this.local.stopAll()}}class Vs extends Ri{onStored;setOnStored(e){this.onStored=e}put(e){const t=super.get(e.id)?.stateRevision||0,n=super.put(pn.parse({...e,stateRevision:Math.max(e.stateRevision||0,t)+1}));return this.onStored?.(n),n}}class Hs{nodeId;paths;localFolders;nodeRuntimes;controlledInstances;models;modelAssignments;modelEnvironments;updateJobs;node;listenerPort;containerUrlOverride;platform;constructor(e,t,n,i,r,s){this.paths=e,this.nodeId=t,this.localFolders=new Ri(e.localFoldersDir,{schema:At,sanitize:$e}),this.nodeRuntimes=new Ri(e.nodeRuntimesDir,{schema:nn}),this.controlledInstances=new Vs(e.controlledInstancesDir,{schema:pn,sanitize:e=>In(e,e=>{console.warn(JSON.stringify({message:"legacy controlled instance field was ignored",...e}))})}),this.models=new _r(e.nodeModelsDir,t),this.modelAssignments=new Tr(e.modelAssignmentsDir),this.modelEnvironments=new Er(e.modelEnvironmentsDir),this.updateJobs=new sr(e),this.listenerPort=r,this.platform=s,this.containerUrlOverride=i;const o=As();this.node=tn.parse({id:t,name:t,connectionMode:"direct-http",endpoint:n,controlEndpoint:n,containerEndpoint:this.containerUrl,publicWebBase:n?n.replace(/:\d+$/,""):void 0,status:"online",health:"ok",capabilities:{},labels:{},createdAt:o,updatedAt:o})}init(){this.localFolders.init();for(const e of this.localFolders.list())this.localFolders.put(e);if(this.nodeRuntimes.init(),this.controlledInstances.init(),this.models.init(),this.modelAssignments.init(),this.migrateLegacyModelEnvironments(),this.updateJobs.init(),this.updateJobs.reconcileRollouts(this.controlledInstances.list(),ds()),!this.nodeRuntimes.get("runtime_local_docker")){const e=As();this.nodeRuntimes.put(nn.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(es),t=As();this.nodeRuntimes.put(nn.parse({id:es,nodeId:this.nodeId,name:"Local Runtime",type:"local",status:e?.status||"unknown",accessStrategy:"node-proxy",capabilities:Os(e?.capabilities),labels:{...e?.labels,[ts]:"true"},createdAt:e?.createdAt||t,updatedAt:e?.updatedAt||t}))}for(const e of this.nodeRuntimes.list())e.nodeId!==this.nodeId&&this.nodeRuntimes.put(nn.parse({...e,nodeId:this.nodeId,updatedAt:As()}));for(const e of this.localFolders.list())e.nodeId!==this.nodeId&&this.localFolders.put(At.parse({...e,nodeId:this.nodeId,updatedAt:As()}));this.normalizeInstanceRuntimeVersions()}normalizeInstanceRuntimeVersions(){for(const e of this.controlledInstances.list()){const t=ls(e.build?.packageVersion||e.instanceVersion),n=Cs(this.requireRuntime(e.runtimeId)),i=["created","stopped","failed"].includes(e.status),r=n&&e.runtimeVersion?.desiredVersion===t.desiredVersion?e.runtimeVersion:void 0,s=n?"matched"===t.phase?i?t:{...t,phase:"verifying",matchedAt:void 0}:"failed"===r?.phase&&!1===r.error?.retryable?{...t,phase:"failed",attempt:r.attempt,lastAttemptAt:r.lastAttemptAt,error:r.error}:{...t,attempt:r?.attempt||0,lastAttemptAt:r?.lastAttemptAt}:t;this.controlledInstances.put(pn.parse({...e,ready:!1,runtimeVersion:s,updatedAt:As()}))}}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=As()}runningInstanceCount(){const e=new Set(["created","stopped","failed"]);return this.listInstances().filter(t=>!e.has(t.status)).length}createLocalFolder(e){const t=As(),n=At.parse({...e,id:e.id||Ci("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=As(),n=nn.parse({...e,id:e.id||Ci("runtime"),nodeId:this.nodeId,accessStrategy:e.accessStrategy||(i=e.type,"docker"===i?"direct-port":"node-proxy"),capabilities:e.capabilities||{},labels:rs(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[ts]){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=nn.parse({...n,...t,id:n.id,nodeId:this.nodeId,accessStrategy:t.accessStrategy||n.accessStrategy,capabilities:t.capabilities||n.capabilities,labels:t.labels?rs(t.labels):n.labels,createdAt:n.createdAt,updatedAt:As()});return this.nodeRuntimes.put(i)}deleteRuntime(e){if("true"===this.requireRuntime(e).labels[ts]){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=nn.parse({...n,...e,id:n.id,nodeId:this.nodeId,createdAt:n.createdAt,updatedAt:As()});return this.nodeRuntimes.put(t)}):this.nodeRuntimes.put(nn.parse({...n,status:"unknown",updatedAt:As()}))}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("; "),i=new Error(`Stored instance ${e} is not compatible with protocol ${be}: ${n}`);return Object.assign(i,{statusCode:409,code:"NODE_INSTANCE_PAYLOAD_INVALID"}),i}(e,n.error.issues);return n.data}listInstances(){return this.controlledInstances.list().flatMap(e=>{const t=fn(e);return t.success?[t.data]:[]})}listModels(){const e=new Map;for(const t of this.listInstances()){const n=this.modelAssignments.get(t.id);for(const t of[n?.codexModelHash,n?.claudeModelHash])t&&e.set(t,(e.get(t)||0)+1)}return this.models.list().map(t=>this.publicModel(t,e.get(t.id)||0))}createModel(e){const t=As(),n=Pt(e),i=this.models.get(n),r=St.parse({...e,id:n,enabled:e.enabled??!0,order:e.order??this.nextModelOrder(),labels:e.labels||{},createdAt:i?.createdAt||t,updatedAt:t});return this.publicModel(this.models.put(r),this.modelReferenceIds(n).length)}deployModel(e){const t=Pt(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(St.parse(e));return this.publicModel(n,this.modelReferenceIds(n.id).length)}updateModel(e,t){const n=this.requireModel(e),i=St.parse({...n,...t,key:t.key?.trim()?t.key:n.key,createdAt:n.createdAt,updatedAt:As()}),r=Pt(i),s=this.models.put(St.parse({...i,id:r}));return this.publicModel(s,this.modelReferenceIds(r).length)}deleteModel(e){this.requireModel(e);const t=this.modelReferenceIds(e);if(t.length)throw Object.assign(new Error(`Model ${e} is assigned to ${t.length} instance${1===t.length?"":"s"}.`),{statusCode:409,code:"NODE_MODEL_IN_USE",instanceIds:t});return this.models.delete(e)}assignModels(e,t){const n=this.requireInstance(e);if(this.validateAssignmentRef("codex",t.codexModelHash),this.validateAssignmentRef("claude",t.claudeModelHash),void 0!==t.modelSelection.codexModelHash&&(t.modelSelection.codexModelHash??void 0)!==t.codexModelHash)throw Object.assign(new Error("Codex model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});if(void 0!==t.modelSelection.claudeModelHash&&(t.modelSelection.claudeModelHash??void 0)!==t.claudeModelHash)throw Object.assign(new Error("Claude model selection does not match its node assignment."),{statusCode:400,code:"NODE_MODEL_SELECTION_MISMATCH"});const i=this.modelAssignments.get(e),r=Tt.parse({instanceId:e,codexModelHash:t.codexModelHash,claudeModelHash:t.claudeModelHash,updatedAt:As()});this.modelAssignments.put(r);try{return{assignment:r,instance:this.controlledInstances.put(pn.parse({...n,modelSelection:t.modelSelection,updatedAt:As()}))}}catch(t){throw i?this.modelAssignments.put(i):this.modelAssignments.delete(e),t}}resolvedAssignedModelEnvironment(e){const t=this.modelAssignments.get(e);if(!t){if(this.modelEnvironments.has(e))throw Object.assign(new Error(`Legacy model environment for instance ${e} requires manual migration.`),{statusCode:409,code:"NODE_MODEL_MIGRATION_REQUIRED"});return{}}return{...this.modelEnvironmentForRef("codex",t.codexModelHash),...this.modelEnvironmentForRef("claude",t.claudeModelHash)}}validateAssignmentRef(e,t){if(!t)return;const n=this.requireModel(t);if(n.app!==e)throw Object.assign(new Error(`Model ${n.id} belongs to ${n.app}, not ${e}.`),{statusCode:400,code:"NODE_MODEL_APP_MISMATCH"});if(!n.enabled)throw Object.assign(new Error(`Model ${n.id} is disabled.`),{statusCode:409,code:"NODE_MODEL_DISABLED"})}modelEnvironmentForRef(e,t){if(!t)return{};this.validateAssignmentRef(e,t);const n=this.requireModel(t);return"codex"===e?{OPENAI_API_KEY:n.key,OPENAI_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_BASE_URL:n.endpoint,TASK_HANDOFF_CODEX_MODEL:n.model}:{ANTHROPIC_API_KEY:n.key,ANTHROPIC_BASE_URL:n.endpoint,TASK_HANDOFF_CLAUDE_MODEL:n.model}}requireModel(e){const t=this.models.get(e);if(!t)throw Object.assign(new Error(`Model ${e} was not found on node ${this.nodeId}.`),{statusCode:404,code:"NODE_MODEL_NOT_FOUND"});if(Pt(t)!==t.id)throw Object.assign(new Error(`Stored model ${e} does not match its content hash.`),{statusCode:409,code:"NODE_MODEL_HASH_INVALID"});return t}modelReferenceIds(e){return this.listInstances().filter(t=>{const n=this.modelAssignments.get(t.id);return n?.codexModelHash===e||n?.claudeModelHash===e}).map(e=>e.id)}publicModel(e,t){const{key:n,...i}=e;return _t.parse({...i,keyPreview:n.length<=8?"set":`${n.slice(0,4)}...${n.slice(-4)}`,keySet:!0,referenceCount:t})}nextModelOrder(){return this.models.list().reduce((e,t)=>Math.max(e,t.order),0)+100}migrateLegacyModelEnvironments(){for(const e of this.modelEnvironments.listInstanceIds()){if(!this.controlledInstances.get(e)){this.warnLegacyModelMigration(e,"instance-not-found");continue}if(this.modelAssignments.get(e)){try{this.resolvedAssignedModelEnvironment(e),this.modelEnvironments.delete(e)}catch{this.warnLegacyModelMigration(e,"existing-assignment-invalid")}continue}let t;try{t=this.modelEnvironments.get(e)}catch{this.warnLegacyModelMigration(e,"sidecar-invalid");continue}if(!Object.keys(t).length){this.modelEnvironments.delete(e);continue}if(Object.keys(t).some(e=>!Sr.has(e))){this.warnLegacyModelMigration(e,"unknown-fields");continue}const n=[];try{const i=this.migrateLegacyModelForApp(t,"codex",n),r=this.migrateLegacyModelForApp(t,"claude",n);if(!i&&!r)throw new Error("no complete model configuration");const s={...i?{codexModelHash:i}:{},...r?{claudeModelHash:r}:{}};this.assignModels(e,{modelSelection:s,codexModelHash:i,claudeModelHash:r}),this.resolvedAssignedModelEnvironment(e),this.modelEnvironments.delete(e)}catch{this.modelAssignments.delete(e);for(const e of n)this.models.delete(e);this.warnLegacyModelMigration(e,"mapping-failed")}}}migrateLegacyModelForApp(e,t,n){const i=e["codex"===t?"OPENAI_API_KEY":"ANTHROPIC_API_KEY"],r="codex"===t?e.TASK_HANDOFF_CODEX_BASE_URL||e.OPENAI_BASE_URL:e.ANTHROPIC_BASE_URL,s="codex"===t?e.TASK_HANDOFF_CODEX_MODEL||e.CODEX_MODEL:e.TASK_HANDOFF_CLAUDE_MODEL||e.CLAUDE_MODEL;if(!Boolean(i||r||s))return;if(!i||!r||!s)throw new Error("model configuration incomplete");const o=Pt({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=As();return this.models.put(St.parse({id:o,name:`Migrated ${"codex"===t?"Codex":"Claude"} model`,endpoint:r,key:i,model:s,app:t,enabled:!0,order:this.nextModelOrder(),labels:{migratedFrom:"instance-model-environment"},createdAt:c,updatedAt:c})),n.push(o),o}warnLegacyModelMigration(e,t){console.warn(JSON.stringify({message:"legacy model environment was preserved because it could not be migrated",nodeId:this.nodeId,instanceId:e,reason:t}))}createInstance(e){const t=this.requireRuntime(e.runtimeId),i=As(),r=e.id||Ci("inst"),s=bt.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?Jt.parse(e.image):void 0,a="local"===t.type&&"local-folder"===s.type?n.resolve(s.path):void 0,c=pn.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:ls(),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:Oi(),createdAt:i,updatedAt:i});return this.controlledInstances.put(c)}registerInstance(e,t,n){const i=wn.parse(t),r=As(),s=this.controlledInstances.get(e);if(!s){const t=new Error(`Instance ${e} was not found on node ${this.nodeId}.`);throw Object.assign(t,{statusCode:404,code:"NODE_INSTANCE_NOT_FOUND"}),t}this.validateInstanceReport(s,i,n),xs(i.protocolVersion,`Instance ${e}`);const o=i.build?.packageVersion||i.instanceVersion,a=Cs(this.requireRuntime(s.runtimeId)),c=us(s,o,a),d=pn.parse({...s,name:i.name,status:"registered",health:o===ds()?"ok":"degraded",ready:!a&&o===ds(),connectionStatus:"online",agentStatus:"online",targetStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":"reachable"===i.target.status?"reachable":s.targetStatus,uiAccessStatus:"endpoint-unreachable"===i.target.status?"endpoint-unreachable":s.uiAccessStatus,controlMode:i.controlMode,protocolVersion:i.protocolVersion,instanceVersion:i.instanceVersion,build:i.build,runtimeVersion:c,capabilities:i.capabilities,appInventory:i.appInventory,workspace:i.workspace,target:{...s.target,...i.target},registrationToken:s.registrationToken||i.registrationToken,lastHeartbeatAt:r,updatedAt:r});return this.controlledInstances.put(d)}heartbeatInstance(e,t,n){const i=this.requireInstance(e);this.validateInstanceToken(i,n);const r=zn.parse(t);xs(r.protocolVersion,`Instance ${e}`);const s=As(),o=r.target?{...i.target,...r.target}:i.target,a={...o,status:"unknown"===o.status&&(o.web||o.api)?"reachable":o.status},c="endpoint-unreachable"===a.status?"endpoint-unreachable":"reachable"===a.status?"reachable":i.targetStatus,d=r.build?.packageVersion||i.build?.packageVersion||i.instanceVersion,l=Cs(this.requireRuntime(i.runtimeId)),u=us(i,d,l),m=d===ds()&&(!l||i.ready&&"matched"===i.runtimeVersion?.phase),p=pn.parse({...i,...r,target:a,ready:m&&"failed"!==r.health,health:d===ds()?r.health||i.health:"degraded",runtimeVersion:u,agentStatus:"online",targetStatus:c,uiAccessStatus:c,connectionStatus:"online",build:r.build||i.build,lastHeartbeatAt:s,updatedAt:s});return this.controlledInstances.put(p)}validateInstanceReport(e,t,n){this.validateInstanceToken(e,n||t.registrationToken),t.instanceId&&t.instanceId!==e.id&&ks("INSTANCE_ID_MISMATCH",`Instance ${t.instanceId} cannot register as ${e.id}.`),t.nodeId&&t.nodeId!==this.nodeId&&ks("INSTANCE_NODE_MISMATCH",`Instance ${e.id} belongs to node ${this.nodeId}.`),t.runtimeId&&t.runtimeId!==e.runtimeId&&ks("INSTANCE_RUNTIME_MISMATCH",`Instance ${e.id} belongs to runtime ${e.runtimeId}.`),t.imageSelection&&t.imageSelection.imageId!==e.imageSelection?.imageId&&ks("INSTANCE_IMAGE_MISMATCH",`Instance ${e.id} belongs to image ${e.imageSelection?.imageId}.`)}validateInstanceToken(e,t){e.registrationToken&&t===e.registrationToken||ks("INSTANCE_REGISTRATION_TOKEN_INVALID",`Invalid registration token for instance ${e.id}.`)}context(e,t=this.resolvedAssignedModelEnvironment(e.id)){const n=e.imageSnapshot||Jt.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:Ns(e),image:n,node:this.node,runtime:this.requireRuntime(e.runtimeId),instance:e,nodeAgentUrl:this.containerUrl,modelEnv:t}}}class qs{app;state;settings;sockets=new Set;config;source;status="error";error;constructor(e){this.app=e.app,this.state=e.state,this.settings=e.settings,this.config=e.config,this.source=e.source,this.app.server.on("connection",e=>{this.sockets.add(e),e.once("close",()=>this.sockets.delete(e))})}current(){return on.parse({...this.config,host:bs(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:bs(this.config.bindScope),port:this.config.port,error:this.error},"node agent TCP listener failed to start; Unix IPC remains available")}return this.current()}async update(e){const t=an.parse(e);if(t.bindScope===this.config.bindScope&&t.port===this.config.port)return this.current();if(t.port!==this.config.port){const e=this.state.runningInstanceCount();if(e>0){const t=new Error(`Cannot change the node agent port while ${e} controlled instance(s) are running.`);throw Object.assign(t,{statusCode:409,code:"NODE_AGENT_LISTENER_PORT_IN_USE_BY_INSTANCES",blockingInstanceCount:e}),t}}const n={config:this.config,source:this.source,status:this.status,error:this.error};await this.stop();try{await this.listen(t)}catch(e){await this.restore(n);const i=new Error(`Failed to bind node agent TCP listener at ${bs(t.bindScope)}:${t.port}: ${e instanceof Error?e.message:String(e)}`);throw Object.assign(i,{statusCode:409,code:"NODE_AGENT_LISTENER_BIND_FAILED"}),i}try{this.settings.put({version:1,externalListener:t})}catch(e){await this.stop(),await this.restore(n);const t=new Error(`Failed to persist node agent TCP listener: ${e instanceof Error?e.message:String(e)}`);throw Object.assign(t,{statusCode:500,code:"NODE_AGENT_LISTENER_PERSIST_FAILED"}),t}return this.config=t,this.source="persisted",this.status="listening",this.error=void 0,this.state.setListenerPort(t.port),this.current()}async shutdown(){await this.stop()}async restore(e){if(this.config=e.config,this.source=e.source,this.status=e.status,this.error=e.error,"listening"===e.status)try{await this.listen(e.config)}catch(e){this.status="error",this.error=`Failed to restore previous listener: ${e instanceof Error?e.message:String(e)}`,this.app.log.error({error:this.error},"node agent TCP listener rollback failed")}this.state.setListenerPort(e.config.port)}async listen(e){await new Promise((t,n)=>{const i=e=>{this.app.server.off("listening",r),n(e)},r=()=>{this.app.server.off("error",i),t()};this.app.server.once("error",i),this.app.server.once("listening",r),this.app.server.listen({host:bs(e.bindScope),port:e.port})})}async stop(){this.app.server.listening&&await new Promise((e,t)=>{this.app.server.close(n=>n?t(n):e());for(const e of this.sockets)e.destroy()})}}async function Bs(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(pn.parse({...o,status:"starting",updatedAt:As()}));r.diagnostic({instanceId:i,action:"start",reason:s,runtimeId:o.runtimeId,imageId:o.imageSelection?.imageId},"node instance start requested");const a=e.controlledInstances.put(pn.parse({...o,status:"starting",ready:!1,updatedAt:As()})),c=t.forRuntime(e.requireRuntime(a.runtimeId)),d=await c.start(e.context(a)),l=await vs(n,pn.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:As()})),u=Ks(a,e.requireInstance(i),{...d,target:d.target?{...d.target,status:l}:void 0,workspace:d.workspace?{error:void 0,...d.workspace}:void 0,targetStatus:l,uiAccessStatus:l}),m=e.controlledInstances.put(u);return r.diagnostic({instanceId:i,action:"start",reason:s,status:m.status,connectionStatus:m.connectionStatus,targetStatus:m.targetStatus,targetWeb:m.target.web,containerName:m.runtime.containerName},"node instance start completed"),m}function Ks(e,t,n){const i=t.stateRevision>e.stateRevision&&t.lastHeartbeatAt!==e.lastHeartbeatAt&&"online"===t.agentStatus;return pn.parse({...t,...n,...i?{status:t.status,health:t.health,connectionStatus:t.connectionStatus,agentStatus:t.agentStatus,targetStatus:t.targetStatus,uiAccessStatus:t.uiAccessStatus}:{},ready:!!i&&t.ready,target:n.target?i?{...n.target,...t.target}:{...t.target,...n.target}:t.target,workspace:n.workspace?i?{...n.workspace,...t.workspace}:{...t.workspace,...n.workspace}:t.workspace,runtime:n.runtime?{...t.runtime,...n.runtime}:t.runtime,updatedAt:As()})}function Gs(e,t){const n=t instanceof Error?t.message:String(t);return pn.parse({...e,status:"failed",ready:!1,health:"failed",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",workspace:{...e.workspace,error:n},updatedAt:As()})}function Js(e){return pn.parse({...e,health:"unknown",connectionStatus:"offline",agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",target:{...e.target,status:"unknown"},updatedAt:As()})}async function Ws(e={}){const i=e.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,r=Number(e.port||process.env.TASK_HANDOFF_NODE_AGENT_PORT||"8091"),o=`http://127.0.0.1:${r}`,m=e.containerUrl||process.env.TASK_HANDOFF_NODE_AGENT_CONTAINER_URL,p=Si(e.dataDir),g=e.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,h=e.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID,I=new Yr(p),y=I.resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID),A=e.connectionMode||("local-ipc"===process.env.TASK_HANDOFF_NODE_AGENT_CONNECTION_MODE?"local-ipc":"local-loopback"),w=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||Wi(p.dataDir),z="local-ipc"===A?`ipc://${encodeURIComponent(w)}`:o,N=e.platform||process.platform,v=e.arch||process.arch,S=new Hs(p,y,o,m,r,N);S.node.connectionMode=A,S.node.controlEndpoint=z,S.node.endpoint=z,S.init();const E=e.dockerCommandRunner||Tn,_=new xn(E,e.dockerTerminalCommandRunner),T=new On(E,{publishHost:"127.0.0.1",imageService:_}),k=new Us(new $s(T,E,N,v),new Fs(e.dockerCommandRunner||Tn,p,()=>S.localNodeAgentUrl,function(){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV?.trim();if(!e){const e=process.env.TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND?.trim();return e?e.split(/\s+/):void 0}let t;try{t=JSON.parse(e)}catch{throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be valid JSON."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"})}if(!Array.isArray(t)||!t.length||t.some(e=>"string"!=typeof e||!e))throw Object.assign(new Error("TASK_HANDOFF_LOCAL_CONTROLLED_COMMAND_ARGV must be a non-empty string array."),{code:"LOCAL_CONTROLLED_COMMAND_INVALID"});return t}())),x=e.updateCommandRunner||e.dockerCommandRunner||Tn,C=e.fetchImpl||fetch,O=new pr({cacheDir:n.join(p.dataDir,"runtime-artifacts"),fetchImpl:C}),R=e.resolveRuntimeArtifactRelease||((e,t,n)=>gr(e,t,n,C)),D=async(t,n,i)=>{const r=await n.artifactTarget(i);if(e.resolveRuntimeArtifact)return e.resolveRuntimeArtifact(t,r.platform,r.arch);const s=await R(t,r.platform,r.arch);if(s.identity.launcherAbi>r.launcherAbi)throw Object.assign(new Error(`Runtime requires launcher ABI ${s.identity.launcherAbi}, but ${r.platform}-${r.arch} provides ABI ${r.launcherAbi}.`),{code:"INSTANCE_BASE_RUNTIME_INCOMPATIBLE",retryable:!1});return O.resolve(s.identity,s.source)},j=e=>k.forRuntime(S.requireRuntime(e.runtimeId)),P=e=>{const t=j(e);return Ls(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})},L=e=>Boolean(P(e)),$=(e,t)=>{const n=S.context(e);return D(t,M(e),n)},F=c({logger:e.logger??!0}),U={requests:0,active:0,completed:0,aborted:0,limitRejected:0,responseBytes:0,totalDurationMs:0,maxResponseBytes:hs()};F.decorate("nodeAgentState",S),await F.register(d);const V=new Qn(S,i,{logger:F.log,safetyIntervalMs:Number(process.env.TASK_HANDOFF_EVENT_CONNECTION_SAFETY_INTERVAL_MS)||void 0}),H=new hr(S.controlledInstances,ds,{isInstalled:async(e,t)=>{const n=await $(e,t);return M(e).inspectRuntime(S.context(e),n.identity)},install:async(e,t)=>{const n=M(e);await n.installRuntime(S.context(e),await $(e,t))},restart:async e=>{const t=j(e),n=S.requireInstance(e.id),i=S.controlledInstances.put(pn.parse({...n,build:void 0,instanceVersion:void 0,ready:!1,updatedAt:As()})),r=await t.restart(S.context(i)),s=S.requireInstance(e.id);S.controlledInstances.put(Ks(i,s,r))},rollback:async e=>M(e).rollbackRuntime(S.context(e)),onForcedDrain:e=>F.log.warn({instanceId:e.id},"runtime convergence drain deadline reached; restarting instance")},{drainTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_DRAIN_TIMEOUT_MS)||void 0,verificationTimeoutMs:Number(process.env.TASK_HANDOFF_RUNTIME_VERIFY_TIMEOUT_MS)||void 0,maxAttempts:Number(process.env.TASK_HANDOFF_RUNTIME_MAX_ATTEMPTS)||void 0});S.controlledInstances.setOnStored(e=>{V.publishInstanceLifecycle(e),S.updateJobs.reconcileRollouts(S.listInstances(),ds())}),V.start();for(const e of S.listInstances())L(e)&&!["created","stopped","failed","provisioning"].includes(e.status)&&H.schedule(e.id).catch(t=>F.log.error({instanceId:e.id,error:t},"runtime convergence recovery failed"));F.decorate("nodeAgentEventForwarder",V);const q=new oi(E,()=>S.listInstances().filter(e=>"docker"===S.requireRuntime(e.runtimeId).type),e=>V.publish("instance.metrics.snapshot",e,{instanceId:e.instanceId}));q.start(),F.decorate("nodeAgentRuntimeMetrics",q);const B=(ne=process.env.TASK_HANDOFF_DIAGNOSTIC_LOGS,["1","true","yes","on"].includes(String(ne||"").trim().toLowerCase())),K=new kr(I,y,g,h),G=(e,t)=>{B&&F.log.info(e,t)},J={diagnostic:G,warn:(e,t)=>F.log.warn(e,t)},W=(e,t,n)=>{const i=n&&"object"==typeof n&&!Array.isArray(n)?n.protocolVersion:void 0;if("string"!=typeof i||i===be)return n;const r=({field:n,action:r})=>F.log.warn({instanceId:e,report:t,protocolVersion:i,expectedProtocolVersion:be,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","name","projectId","source","nodeId","runtimeId","imageSelection","instanceVersion","protocolVersion","build","controlMode","capabilities","appInventory","target","workspace","registrationToken"],r=new Set([...i,"imageId"]);for(const e of Object.keys(n))r.has(e)||t?.({field:e,action:"ignored"});return Object.prototype.hasOwnProperty.call(n,"imageId")&&t?.({field:"imageId",action:"migrated"}),{...bn(n,i),imageSelection:Le(n.imageSelection,n.imageId)}}(n,r):function(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return e;const n=["status","health","protocolVersion","build","capabilities","appInventory","apps","aiSessions","triggers","workspace","target"],i=new Set(n);for(const n of Object.keys(e))i.has(n)||t?.({field:n,action:"ignored"});return bn(e,n)}(n,r)},Y=async(e,t)=>{try{let t=S.requireInstance(e);"failed"===t.runtimeVersion?.phase&&L(t)&&(t=S.controlledInstances.put(pn.parse({...t,ready:!1,runtimeVersion:ls(fr(t)),updatedAt:As()})));const n=S.requireRuntime(t.runtimeId);await Bs(S,k,C,e,J);const i=S.requireInstance(e);if("docker"===n.type&&"ready"!==i.imageProvisioning?.phase)return V.syncNow(),i;const r=L(S.requireInstance(e))?await H.schedule(e,{startRequested:!0}):S.requireInstance(e);if(L(r)&&"failed"===r.runtimeVersion?.phase)throw Object.assign(new Error(r.runtimeVersion.error?.message||`Instance ${e} runtime convergence failed.`),{statusCode:503,...r.runtimeVersion.error||{code:"INSTANCE_RUNTIME_INSTALL_FAILED",retryable:!0}});return await Es(C,r,"start",J),V.syncNow(),r}catch(n){const i=Gs(S.requireInstance(e),n);throw S.controlledInstances.put(i),V.syncNow(),J.warn({instanceId:e,action:"start",reason:t,error:n instanceof Error?n.message:String(n)},"node instance start failed"),n}},X=e=>{e.imageProvisioning&&async function(t,n,i,r,s,o,a){const c=e=>{const n=t.controlledInstances.get(i);n&&n.imageProvisioning?.generation===r&&n.imageSnapshot&&(t.controlledInstances.put(pn.parse({...n,status:"starting"===n.status?"starting":"provisioning",imageProvisioning:{...n.imageProvisioning,phase:e,error:void 0,updatedAt:As()},updatedAt:As()})),s())},d=t.controlledInstances.get(i);if(!d?.imageSnapshot||d.imageProvisioning?.generation!==r)return;let l=0,u=!1;try{const m=await n.ensure(d.imageSnapshot.requestedReference,c,e=>{u=!0,l=e.sequence,a?.(e)});u&&a?.({sequence:l+1,outcome:"succeeded"});const p=t.controlledInstances.get(i);if(!p?.imageSnapshot||p.imageProvisioning?.generation!==r)return;t.controlledInstances.put(pn.parse({...p,status:"starting"===p.status?"starting":"created",health:"unknown",imageSnapshot:{...p.imageSnapshot,requestedReference:m.requestedReference,resolvedDigest:m.resolvedDigest,resolvedReference:m.resolvedReference},imageProvisioning:{...p.imageProvisioning,phase:"ready",error:void 0,updatedAt:As()},updatedAt:As()})),s(),o.diagnostic({instanceId:i,action:"image.provision",reference:m.requestedReference,digest:m.resolvedDigest,pulled:m.pulled},"node instance image provisioning completed"),"starting"===p.status&&await((async e=>{await Y(e,"image-ready").catch(()=>{})})(e.id))}catch(e){u&&a?.({sequence:l+1,outcome:"failed"});const n=t.controlledInstances.get(i);if(!n?.imageProvisioning||n.imageProvisioning.generation!==r)return;const c=e instanceof Error?e.message:String(e);t.controlledInstances.put(pn.parse({...n,status:"failed",health:"failed",imageProvisioning:{...n.imageProvisioning,phase:"failed",error:c,updatedAt:As()},updatedAt:As()})),s(),o.warn({instanceId:i,action:"image.provision",reference:n.imageProvisioning.requestedReference,error:c},"node instance image provisioning failed")}}(S,_,e.id,e.imageProvisioning.generation,()=>V.syncNow(),J,t=>{const n={instanceId:e.id,generation:e.imageProvisioning.generation,requestedReference:e.imageProvisioning.requestedReference,observedAt:As()};if("outcome"in t)V.publish(Xt,{...n,sequence:1e3*t.sequence,outcome:t.outcome},{instanceId:e.id});else for(const[i,r]of function(e,t=6e4){const n=[];for(let i=0;i<e.length;i+=t)n.push(e.slice(i,i+t));return n}(t.data).entries())V.publish(Yt,{...n,sequence:1e3*t.sequence+i,data:r,...t.replay?{replay:!0}:{}},{instanceId:e.id})})},Z=async e=>{const t=new Map;for(const e of k.managedAdapters()){const n=await e.artifactTarget();t.set(`${n.platform}-${n.arch}`,{adapter:e})}for(const e of S.listInstances()){const n=P(e);if(!n)continue;const i=S.context(e),r=await n.artifactTarget(i);t.set(`${r.platform}-${r.arch}`,{adapter:n,context:i})}return(await Promise.all([...t.values()].map(({adapter:t,context:n})=>D(e,t,n)))).sort((e,t)=>`${e.identity.platform}/${e.identity.arch}`.localeCompare(`${t.identity.platform}/${t.identity.arch}`))},Q=async e=>{const t=ee(),n=await async function(e){const t=await async function(e,t,n){const i=function(e){return"stable"===e?"latest":e}(n),r=await e(ir(),["view",`${t}@${i}`,"version","--json"]).catch(e=>{if(!function(e){if(!e||"object"!=typeof e)return!1;const t=e,n=[t.message,t.details?.stdout,t.details?.stderr].filter(e=>"string"==typeof e).join("\n");return/\bE404\b/i.test(n)}(e))throw e});if(!r)return;const s=JSON.parse(r.stdout);if("string"!=typeof s)throw new Error(`npm did not resolve ${t}@${i} to one version.`);return s}(e.runCommand,"@task-handoff/node-agent",e.channel);if(!t)return function(e){return pt.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:nr()})}({channel:e.channel,currentVersion:e.currentVersion,impact:e.impact});const n=function(e,t){if(!e)return!0;const n=f.valid(e),i=f.valid(t);return n&&i?f.gt(i,n):e!==t}(e.currentVersion,t),i=n?await async function(e,t,n){const i=await e(ir(),["view",`${t}@${n}`,"dist.integrity","--json"]),r=JSON.parse(i.stdout);if("string"!=typeof r||!/^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/.test(r))throw Object.assign(new Error(`npm did not return immutable integrity metadata for ${t}@${n}.`),{statusCode:502,code:"NODE_UPDATE_PREFLIGHT_FAILED",retryable:!0});return r}(e.runCommand,"@task-handoff/node-agent",t):void 0;return pt.parse({source:"npm",channel:e.channel,currentVersion:e.currentVersion,availableVersion:t,...i?{artifactRef:`npm:@task-handoff/node-agent@${t}#${i}`}:{},runtimeArtifacts:e.runtimeArtifacts||[],impact:e.impact||{runningInstanceCount:0,stoppedInstanceCount:0,activeInstanceCount:0,restartInstanceCount:0,runningInstanceIds:[],stoppedInstanceIds:[],activeInstanceIds:[]},updateAvailable:n,checkedAt:nr()})}({channel:e.channel,currentVersion:ds(),runCommand:x,impact:t});if(!n.updateAvailable)return n;const i=await Z(n.availableVersion),r={...n,runtimeArtifacts:i.map(e=>e.identity),preflightToken:Oi()};return te.set(r.preflightToken,{result:r,expiresAt:Date.now()+6e5}),r},ee=()=>{const e=S.listInstances(),t=e.filter(e=>!["created","stopped","failed"].includes(e.status)),n=t.filter(e=>e.apps.runningCount>0||e.aiSessions.runningCount>0);return{runningInstanceCount:t.length,stoppedInstanceCount:e.length-t.length,activeInstanceCount:n.length,restartInstanceCount:t.length,runningInstanceIds:t.map(e=>e.id).sort(),stoppedInstanceIds:e.filter(e=>!t.includes(e)).map(e=>e.id).sort(),activeInstanceIds:n.map(e=>e.id).sort()}},te=new Map;var ne;F.setErrorHandler((e,t,n)=>{const i=function(e){if(e instanceof u.z.ZodError)return{statusCode:400,code:"VALIDATION_ERROR",message:e.issues.map(e=>`${e.path.join(".")||"body"}: ${e.message}`).join("; ")};const t=e&&"object"==typeof e?e:{};return{statusCode:"number"==typeof t.statusCode?t.statusCode:500,code:"string"==typeof t.code?t.code:"NODE_AGENT_ERROR",message:e instanceof Error?e.message:String(e)}}(e);(B||i.statusCode>=500)&&(i.statusCode>=500?F.log.error.bind(F.log):F.log.warn.bind(F.log))({method:t.method,url:t.url,statusCode:i.statusCode,errorCode:i.code,error:i.message},"node agent request failed"),n.code(i.statusCode).send({error:{code:i.code,message:i.message,...e&&"object"==typeof e&&"string"==typeof e.expectedVersion?{expectedVersion:e.expectedVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.actualVersion?{actualVersion:e.actualVersion}:{},...e&&"object"==typeof e&&"string"==typeof e.phase?{phase:e.phase}:{},...e&&"object"==typeof e&&"boolean"==typeof e.retryable?{retryable:e.retryable}:{},...e&&"object"==typeof e&&"number"==typeof e.blockingInstanceCount?{blockingInstanceCount:e.blockingInstanceCount}:{}}})}),F.addHook("preHandler",async e=>{const t=K.verify(e);if(t)e.nodeAgentAuthKeyId=t;else if(ys(e)){if(i&&fs(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}else if("/api/node-agent/pairing/complete"!==e.url.split("?")[0]&&!function(e){const t=e.split("?")[0];return/^\/api\/node-agent\/instances\/[^/]+\/(register|heartbeat)$/.test(t)}(e.url)){if(K.hasRemoteSecrets()){const e=new Error("Node agent HMAC signature is required.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_HMAC_SIGNATURE_REQUIRED"}),e}if(!function(e){return Is(e.ip)||Is(e.socket.remoteAddress)||!e.ip&&!e.socket.remoteAddress&&!e.socket.remoteFamily}(e)){const e=new Error("Local node agent access is only accepted from loopback or local IPC connections.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_LOCAL_TOKEN_REQUIRES_LOOPBACK"}),e}if(i&&fs(e.headers)!==i){const e=new Error("Invalid node agent token.");throw Object.assign(e,{statusCode:401,code:"NODE_AGENT_UNAUTHORIZED"}),e}}}),F.addHook("onClose",async()=>{q.stop(),V.stop();for(const e of S.listInstances())H.cancel(e.id);await async function(e,t){await t.stopAll();for(const t of e.listInstances())"local"===e.requireRuntime(t.runtimeId).type&&e.controlledInstances.put(Js(t))}(S,k)}),F.decorate("nodeAgentRestoreLocalInstances",async()=>{for(const e of S.listInstances().filter(e=>["provisioning","starting"].includes(e.status)&&"ready"!==e.imageProvisioning?.phase&&"docker"===S.requireRuntime(e.runtimeId).type))X(e);const e=S.listInstances().filter(e=>"local"===S.requireRuntime(e.runtimeId).type&&Ps.has(e.status));for(const t of e)try{await Bs(S,k,C,t.id,J,"restore"),await Es(C,S.requireInstance(t.id),"start",J)}catch(e){S.controlledInstances.put(Gs(S.requireInstance(t.id),e)),G({instanceId:t.id,action:"restore",error:e instanceof Error?e.message:String(e)},"node local instance restore failed")}}),F.get("/api/node-agent/health",async()=>{return{data:{ok:!0,role:"node-agent",nodeId:y,platform:is(N),arch:process.arch,protocolVersion:be,build:(e="node-agent",{component:e,packageName:"@task-handoff/node-agent",packageVersion:ds(),protocolVersion:be,buildId:cs("TASK_HANDOFF_BUILD_ID"),builtAt:cs("TASK_HANDOFF_BUILT_AT"),gitCommit:cs("TASK_HANDOFF_GIT_COMMIT"),imageRef:cs("TASK_HANDOFF_IMAGE_REF"),imageDigest:cs("TASK_HANDOFF_IMAGE_DIGEST")}),instanceProxy:{...U},serverTime:(new Date).toISOString()}};var e});const ie=e=>{if(!ys(e)){const e=new Error("Node agent TCP listener settings are available only over local Unix IPC.");throw Object.assign(e,{statusCode:403,code:"NODE_AGENT_LISTENER_LOCAL_IPC_ONLY"}),e}if(!F.nodeAgentListenerManager){const e=new Error("Node agent TCP listener manager is not initialized.");throw Object.assign(e,{statusCode:503,code:"NODE_AGENT_LISTENER_UNAVAILABLE"}),e}return F.nodeAgentListenerManager};return F.get("/api/node-agent/settings/external-listener",async e=>({data:ie(e).current()})),F.patch("/api/node-agent/settings/external-listener",async e=>({data:await ie(e).update(e.body)})),F.get("/api/node-agent/updates/jobs",async()=>({data:S.updateJobs.list()})),F.post("/api/node-agent/updates/check",async e=>({data:await Q(mt.parse(e.body))})),F.post("/api/node-agent/updates/apply",async(e,i)=>{const r=as.parse(e.body),o=await(async e=>{const t=te.get(e.preflightToken);if(te.delete(e.preflightToken),!t||t.expiresAt<=Date.now()){const e=new Error("The update preflight is missing or expired. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_EXPIRED"}),e}const n=t.result;if(n.channel!==e.channel||n.availableVersion!==e.targetVersion||n.currentVersion!==ds()||JSON.stringify(n.impact)!==JSON.stringify(ee())){const e=new Error("The update target or affected instances changed after preflight. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"}),e}const i=await Z(n.availableVersion);if(JSON.stringify(n.runtimeArtifacts)!==JSON.stringify(i.map(e=>e.identity))){const e=new Error("The runtime artifacts changed after preflight. Check for updates again.");throw Object.assign(e,{statusCode:409,code:"UPDATE_PREFLIGHT_STALE"}),e}return n})(r);if(!o.supported){const e=new Error(o.reason||"The requested update is not supported.");throw Object.assign(e,{statusCode:400,code:"UPDATE_UNSUPPORTED"}),e}if(!o.updateAvailable){const e=new Error(o.reason||"No update is available for the selected channel.");throw Object.assign(e,{statusCode:409,code:"UPDATE_NOT_AVAILABLE"}),e}const a=S.updateJobs.create(y,o),c=("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)?n.dirname(s.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:b&&"SCRIPT"===b.tagName.toUpperCase()&&b.src||new URL("cli.js",document.baseURI).href)):__dirname,{worker:d,packaged:l,expectedWorker:u}=function(e,i=t.existsSync){const r=[n.resolve(e,"..","bin","task-handoff-node-update-worker"),n.resolve(e,"..","..","bin","task-handoff-node-update-worker")],s=r.find(i),o=n.resolve(e,"..","..","..","..","scripts","node-update-worker.cjs");return s?{worker:s,packaged:!0,expectedWorker:r[0]}:i(o)?{worker:o,packaged:!1,expectedWorker:r[0]}:{worker:void 0,packaged:!1,expectedWorker:r[0]}}(c);if(!d){S.updateJobs.patch(a.id,{status:"failed",rollout:{...a.rollout,phase:"failed"},error:{code:"NODE_UPDATE_FAILED",message:`Update worker was not found: ${u}`,retryable:!1},completedAt:As()});const e=new Error(`Node agent update worker was not found: ${u}`);throw Object.assign(e,{statusCode:500,code:"UPDATE_WORKER_NOT_FOUND"}),e}return await x("systemd-run",["--unit",`task-handoff-update-${a.id}`,"--collect","--property=Type=exec",...l?[d]:[process.execPath,d],"--job-file",S.updateJobs.records.filePath(a.id),"--target-version",a.toVersion,"--npm-command",ir()]),i.code(202).send({data:a})}),F.post("/api/node-agent/pairing/invites",async(e,t)=>{const n=I.createPairingInvite(Pr.parse(e.body||{}));return t.code(201).send({data:{nodeId:y,joinToken:n.token,expiresAt:n.expiresAt}})}),F.post("/api/node-agent/pairing/complete",async(e,t)=>{const n=I.completePairingInvite(Mr.parse(e.body));return t.code(201).send({data:{nodeId:y,keyId:n.keyId,secret:n.secret,pairedAt:n.pairedAt}})}),F.get("/api/node-agent/remotes",async e=>({data:I.listRemoteControlPlanes(e.nodeAgentAuthKeyId)})),F.delete("/api/node-agent/remotes/:keyId",async e=>{const t=u.z.string().trim().min(1).max(160).parse(e.params.keyId);return{data:{deleted:I.deleteRemoteControlPlane(t,e.nodeAgentAuthKeyId)}}}),F.post("/api/node-agent/remotes/connect",async(e,t)=>{const n=Lr.parse(e.body),i=function(e){const t=new URL(e);if("http:"!==t.protocol&&"https:"!==t.protocol){const e=new Error("Control-plane URL must use http or https.");throw Object.assign(e,{statusCode:400,code:"NODE_AGENT_REMOTE_CONTROL_PLANE_URL_INVALID"}),e}return t.toString().replace(/\/$/,"")}(n.controlPlaneUrl),r=I.createRemoteControlPlane({url:i,...n.controlPlaneName?{name:n.controlPlaneName}:{},active:!1!==n.activate}),s=await async function(e,t,n){const i=await e(new URL("/api/node-join/complete",t).toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok){const e=new Error(r.error?.message||`Control-plane node join failed with HTTP ${i.status}.`);throw Object.assign(e,{statusCode:i.status,code:r.error?.code||"NODE_AGENT_REMOTE_JOIN_FAILED"}),e}return r.data||{}}(C,i,{joinToken:n.joinToken,nodeId:y,nodeName:S.node.name,keyId:r.keyId,secret:r.secret,pairedAt:r.pairedAt}),o=I.upsertRemoteControlPlane({...r,..."string"==typeof s.name&&s.name?{name:n.controlPlaneName||s.name}:{}});let a,c=!1!==o.active?"saved":"disabled";if(!1!==o.active&&F.nodeAgentReverseTunnels)try{F.nodeAgentReverseTunnels.connect({url:i,keyId:o.keyId,secret:o.secret}),c="connecting"}catch(e){c="failed",a=e instanceof Error?e.message:String(e)}return t.code(201).send({data:{remote:{id:o.id,url:o.url,keyId:o.keyId,pairedAt:o.pairedAt,active:!1!==o.active},tunnel:{status:c,...a?{error:a}:{}}}})}),F.get("/api/node-agent/runtimes",async()=>({data:S.nodeRuntimes.list()})),F.post("/api/node-agent/runtimes",async(e,t)=>t.code(201).send({data:S.createRuntime(zi.parse(e.body))})),F.patch("/api/node-agent/runtimes/:id",async e=>({data:S.updateRuntime(e.params.id,Ni.parse(e.body))})),F.delete("/api/node-agent/runtimes/:id",async e=>({data:{deleted:S.deleteRuntime(e.params.id)}})),F.post("/api/node-agent/runtimes/:id/check",async e=>{const t=S.requireRuntime(e.params.id);return{data:await S.checkRuntime(t.id,k.forRuntime(t))}}),F.get("/api/node-agent/local-folders",async()=>({data:S.localFolders.list()})),F.get("/api/node-agent/folders/tree",async e=>({data:fi(Ai.parse(e.query))})),F.post("/api/node-agent/local-folders",async(e,t)=>t.code(201).send({data:S.createLocalFolder(yi.parse(e.body))})),F.delete("/api/node-agent/local-folders/:id",async e=>({data:{deleted:S.localFolders.delete(e.params.id)}})),F.get("/api/node-agent/models",async()=>({data:S.listModels()})),F.post("/api/node-agent/models",async(e,t)=>t.code(201).send({data:S.createModel(Ot.parse(e.body))})),F.put("/api/node-agent/models/:id/deploy",async e=>{const t=e.params.id,n=Dt.parse(e.body);if(n.id!==t)throw Object.assign(new Error(`Model payload id ${n.id} does not match route id ${t}.`),{statusCode:400,code:"NODE_MODEL_ID_MISMATCH"});return{data:S.deployModel(n)}}),F.patch("/api/node-agent/models/:id",async e=>({data:S.updateModel(e.params.id,Rt.parse(e.body))})),F.delete("/api/node-agent/models/:id",async e=>({data:{deleted:S.deleteModel(e.params.id)}})),F.get("/api/node-agent/instances",async()=>({data:S.listInstances()})),F.post("/api/node-agent/instances",async(e,t)=>{const n=S.createInstance(bi.parse(e.body));return V.syncNow(),n.imageProvisioning&&X(n),t.code(201).send({data:n})}),F.post("/api/node-agent/instances/:id/image-provisioning/retry",async e=>{const t=function(e,t){const n=e.requireInstance(t);if("docker"!==e.requireRuntime(n.runtimeId).type||!n.imageSnapshot){const e=new Error(`Instance ${t} does not use a Docker image.`);throw Object.assign(e,{statusCode:400,code:"INSTANCE_IMAGE_PROVISIONING_UNSUPPORTED"}),e}if("failed"!==n.status||"failed"!==n.imageProvisioning?.phase){const e=new Error(`Instance ${t} does not have failed image provisioning to retry.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_IMAGE_PROVISIONING_NOT_FAILED"}),e}const i=As();return e.controlledInstances.put(pn.parse({...n,status:"provisioning",health:"unknown",imageProvisioning:{phase:"checking-image",requestedReference:n.imageSnapshot.requestedReference,generation:(n.imageProvisioning?.generation||0)+1,startedAt:i,updatedAt:i},updatedAt:i}))}(S,e.params.id);return V.syncNow(),X(t),{data:t}}),F.patch("/api/node-agent/instances/:id",async e=>{const t=e.params.id,n=S.requireInstance(t),i=wi.parse(e.body),r=pn.parse({...n,...i,...i.config?{config:{...n.config,...i.config}}:{},updatedAt:As()}),s=S.controlledInstances.put(r);return V.syncNow(),{data:s}}),F.put("/api/node-agent/instances/:id/model-assignment",async e=>{const t=e.params.id,n=S.assignModels(t,jt.parse(e.body));return await _s(C,S,t),{data:n}}),F.post("/api/node-agent/instances/:id/register",async(e,t)=>{const n=e.params.id,i=W(n,"register",e.body),r=S.registerInstance(n,wn.parse(i),fs(e.headers));return V.syncNow(),G({instanceId:n,action:"register",protocolVersion:r.protocolVersion,build:r.build,targetStatus:r.targetStatus,targetStrategy:r.target.strategy},"node instance registered"),!L(r)||r.ready&&"matched"===r.runtimeVersion?.phase||H.schedule(n).catch(e=>F.log.error({instanceId:n,error:e},"runtime convergence after registration failed")),t.code(201).send({data:r})}),F.post("/api/node-agent/instances/:id/heartbeat",async e=>{const t=e.params.id,n=W(t,"heartbeat",e.body),i=S.heartbeatInstance(t,zn.parse(n),fs(e.headers));return V.syncNow(),G({instanceId:t,action:"heartbeat",status:i.status,health:i.health,protocolVersion:i.protocolVersion,build:i.build,targetStatus:i.targetStatus,apps:i.apps.runningCount},"node instance heartbeat accepted"),!L(i)||i.ready&&"matched"===i.runtimeVersion?.phase||H.schedule(t).catch(e=>F.log.error({instanceId:t,error:e},"runtime convergence after heartbeat failed")),{data:i}}),F.get("/api/node-agent/events",{websocket:!0},e=>{const t=e;t.send(JSON.stringify({type:"node-agent.events.connected",nodeId:y,serverTime:(new Date).toISOString()}));const n=V.addOutput(t);t.on("close",n),t.on("error",n)}),F.get("/api/node-agent/docker/images",async()=>({data:await jn(e.dockerCommandRunner)})),F.get("/api/node-agent/instances/:id/metrics",async e=>{const t=e.params.id,n=S.requireInstance(t);if("docker"!==S.requireRuntime(n.runtimeId).type){const e=new Error(`Runtime type ${S.requireRuntime(n.runtimeId).type} does not provide resource metrics.`);throw Object.assign(e,{statusCode:409,code:"INSTANCE_METRICS_UNSUPPORTED"}),e}return{data:await q.snapshot(t)}}),F.post("/api/node-agent/instances/:id/start",async e=>{const t=e.params.id;return os.parse(e.body),{data:await Y(t,"request")}}),F.post("/api/node-agent/instances/:id/runtime/reconcile",async e=>{const t=e.params.id;os.parse(e.body);const n=S.requireInstance(t);S.controlledInstances.put(pn.parse({...n,ready:!1,runtimeVersion:ls(fr(n)),updatedAt:As()}));const i=await H.schedule(t,{startRequested:!["created","stopped"].includes(n.status),resumeCancelled:!0});return V.syncNow(),{data:i}}),F.post("/api/node-agent/instances/:id/stop",async e=>{const t=e.params.id;await H.cancel(t);const n=S.requireInstance(t);G({instanceId:n.id,action:"stop",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance stop requested");const i=k.forRuntime(S.requireRuntime(n.runtimeId)),r=await i.stop(S.context(n)),s=pn.parse({...n,...r,ready:!1,agentStatus:"offline",targetStatus:"unknown",uiAccessStatus:"unknown",updatedAt:As()}),o=S.controlledInstances.put(s);return V.syncNow(),G({instanceId:n.id,action:"stop",status:o.status,connectionStatus:o.connectionStatus,containerName:o.runtime.containerName},"node instance stop completed"),{data:o}}),F.post("/api/node-agent/instances/:id/restart",async e=>{const t=e.params.id,n=S.requireInstance(t);if(os.parse(e.body),L(n)&&(!n.ready||"matched"!==n.runtimeVersion?.phase)){const e=await H.schedule(t,{startRequested:!0});return V.syncNow(),{data:e}}G({instanceId:t,action:"restart",runtimeId:n.runtimeId,imageId:n.imageSelection?.imageId,containerName:n.runtime.containerName},"node instance restart requested");const i=k.forRuntime(S.requireRuntime(n.runtimeId)),r=await i.restart(S.context(n)),s=pn.parse({...n,...r,target:r.target?{...n.target,...r.target}:n.target,updatedAt:As()}),o=await vs(C,s),a=Ks(n,S.requireInstance(t),{...r,target:r.target?{...r.target,status:o}:void 0,targetStatus:o,uiAccessStatus:o}),c=S.controlledInstances.put(a);return await Es(C,c,"restart",J),V.syncNow(),G({instanceId:t,action:"restart",status:c.status,connectionStatus:c.connectionStatus,targetStatus:c.targetStatus,targetWeb:c.target.web,containerName:c.runtime.containerName},"node instance restart completed"),{data:c}}),F.post("/api/node-agent/instances/:id/delete",async e=>{const t=e.params.id,n=S.requireInstance(t);await H.cancel(t),G({instanceId:t,action:"delete",runtimeId:n.runtimeId,containerName:n.runtime.containerName},"node instance delete requested");const i=k.forRuntime(S.requireRuntime(n.runtimeId));await i.delete(S.context(n,{})),G({instanceId:t,action:"delete"},"node instance delete completed");const r=S.controlledInstances.delete(t);return S.modelAssignments.delete(t),S.modelEnvironments.delete(t),V.syncNow(),{data:{deleted:r}}}),F.post("/api/node-agent/instances/:id/proxy",async(e,t)=>{const n=e.params.id,i=Ii.parse(e.body),r=Ts(S.requireInstance(n)),s=i.path.startsWith("/")?i.path:`/${i.path}`;"POST"===i.method&&"/api/apps/sessions"===s&&await _s(C,S,n),G({instanceId:n,action:"proxy",method:i.method,path:s,instanceBase:r},"node instance proxy requested");const o=await C(`${r}${s}`,{method:i.method,headers:{...i.headers},body:ps(i)}),a=o.headers.get("content-type")||"application/octet-stream",c=await o.text();G({instanceId:n,action:"proxy",method:i.method,path:s,statusCode:o.status,contentType:a},"node instance proxy completed"),t.code(o.status).type(a).send(c)}),F.post("/api/node-agent/instances/:id/proxy/stream",{bodyLimit:gs},async(e,t)=>{const n=Date.now();U.requests+=1,U.active+=1;const i=new AbortController;let r=0,s=!1,o=!1;const c=e=>{o||(o=!0,U.active-=1,U.totalDurationMs+=Date.now()-n,U.responseBytes+=r,U[e]+=1)},d=()=>{i.abort(),s&&c("aborted")};e.raw.once("aborted",d),t.raw.once("close",d);try{const n=e.params.id,o=Ii.parse(e.body),d=Ts(S.requireInstance(n)),l=o.path.startsWith("/")?o.path:`/${o.path}`;G({instanceId:n,action:"proxy.stream",method:o.method,path:l,instanceBase:d},"node instance streaming proxy requested");const u=await C(`${d}${l}`,{method:o.method,headers:{...o.headers},body:ps(o),signal:i.signal}),m=Number(u.headers.get("content-length"));if(Number.isFinite(m)&&m>U.maxResponseBytes)return U.limitRejected+=1,i.abort(),t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${U.maxResponseBytes} bytes.`}});t.code(u.status);for(const[e,n]of Object.entries(ms(u.headers)))t.header(e,n);if(!u.body||"HEAD"===o.method)return c("completed"),t.send();const p=new a.Transform({transform(e,t,n){if(r+=e.length,r>U.maxResponseBytes)return U.limitRejected+=1,i.abort(),void n(Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"}));n(null,e)}});return s=!0,p.once("end",()=>c("completed")),p.once("error",()=>c("aborted")),t.send(a.Readable.fromWeb(u.body).pipe(p))}catch(e){throw c("aborted"),e}finally{e.raw.off("aborted",d),s||c("completed")}}),F.post("/api/node-agent/instances/:id/proxy/raw",{bodyLimit:gs},async(e,t)=>{const n=e.params.id,i=Ii.parse(e.body),r=Ts(S.requireInstance(n)),s=i.path.startsWith("/")?i.path:`/${i.path}`;G({instanceId:n,action:"proxy.raw",method:i.method,path:s,instanceBase:r},"node instance raw proxy requested");const o=await C(`${r}${s}`,{method:i.method,headers:{...i.headers},body:ps(i)}),a=Number(o.headers.get("content-length"));if(Number.isFinite(a)&&a>U.maxResponseBytes)return U.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${U.maxResponseBytes} bytes.`}});let c;try{c=await async function(e,t){if(!e.body)return Buffer.alloc(0);const n=[];let i=0;const r=e.body.getReader();for(;;){const{done:e,value:s}=await r.read();if(e)break;if(i+=s.byteLength,i>t)throw await r.cancel("Instance proxy response limit exceeded.").catch(()=>{}),Object.assign(new Error("Instance proxy response limit exceeded."),{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE"});n.push(Buffer.from(s))}return Buffer.concat(n,i)}(o,U.maxResponseBytes)}catch(e){if(!(e instanceof Error)||"INSTANCE_PROXY_RESPONSE_TOO_LARGE"!==e.code)throw e;return U.limitRejected+=1,t.code(502).send({error:{code:"INSTANCE_PROXY_RESPONSE_TOO_LARGE",message:`Instance response exceeds ${U.maxResponseBytes} bytes.`}})}return G({instanceId:n,action:"proxy.raw",method:i.method,path:s,statusCode:o.status,byteLength:c.length},"node instance raw proxy completed"),{data:{status:o.status,headers:ms(o.headers),bodyBase64:c.toString("base64")}}}),F.get("/api/node-agent/instances/:id/proxy/ws/*",{websocket:!0},(e,t)=>{const n=t.params.id,i=t.params["*"]||"",r=t.url.indexOf("?"),s=r>=0?t.url.slice(r):"";let o;try{const r=Ts(S.requireInstance(n)),a=new URL(`/${i}${s}`,`${r}/`);a.protocol="https:"===a.protocol?"wss:":"ws:";const c=function(e){const t=e["sec-websocket-protocol"],n=(Array.isArray(t)?t.join(","):"string"==typeof t?t:"").split(",").map(e=>e.trim()).filter(Boolean);return n.length?n:void 0}(t.headers);G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`,upstreamUrl:a.toString(),protocols:c||[]},"node instance websocket proxy opening"),o=c?new l(a,c):new l(a),o.on("open",()=>{G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`},"node instance websocket proxy opened"),e.on("message",(e,t)=>o?.readyState===l.OPEN&&o.send(function(e,t){return t?e:e.toString()}(e,t))),e.on("close",()=>o?.close()),e.on("error",()=>o?.close())}),o.on("message",(t,n)=>{e.readyState===l.OPEN&&e.send(n?t:t.toString())}),o.on("close",()=>{G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`},"node instance websocket proxy closed"),e.close()}),o.on("error",t=>{G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`,error:t instanceof Error?t.message:String(t)},"node instance websocket proxy failed"),e.close(1011,"Instance websocket proxy failed.")})}catch(t){G({instanceId:n,action:"proxy.ws",path:`/${i}${s}`,error:t instanceof Error?t.message:String(t)},"node instance websocket endpoint unavailable"),o?.close(),e.close(1011,"Instance websocket endpoint is not reachable.")}}),F}function Ys(e){const t=new URL("/api/node-agent/tunnel",e);return t.protocol="https:"===t.protocol?"wss:":"ws:",t.toString()}function Xs(e,t){const n=new URL(t.tunnelUrl);n.searchParams.set("nodeId",t.nodeId);const i=t.secret?Qi({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${n.pathname}${n.search}`}):{},r=new l(n,{headers:i}),s=new Map,o=new Map;let a;const c=e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port,r=new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`);return r.protocol="ws:",r},d=e=>t.secret?Qi({nodeId:t.nodeId,keyId:t.keyId,secret:t.secret,method:"GET",pathWithQuery:`${e.pathname}${e.search}`}):{},u=(e,t=1e3,n="")=>{const i=s.get(e);s.delete(e),i?.upstream?.close(t,n),i?.tunnel?.close(t,n)},m=(e,t,n=!1)=>new Promise((i,r)=>{e.send(t,{binary:n},e=>e?r(e):i())});return r.on("open",()=>{r.send(JSON.stringify({type:"node-agent.identify",nodeId:t.nodeId,serverTime:(new Date).toISOString()})),a=e.nodeAgentEventForwarder?.addOutput(r)}),r.on("close",()=>{for(const e of s.keys())u(e,1001,"Reverse tunnel disconnected.");for(const[e,t]of o)o.delete(e),t.controller.abort(),t.tunnel.close(1001,"Reverse tunnel disconnected.");a?.(),a=void 0}),r.on("message",async i=>{let a;try{a=JSON.parse(String(i))}catch{return void r.send(JSON.stringify({type:"node-agent.error",code:"INVALID_JSON"}))}const p=a&&"object"==typeof a?a:{};if("control-plane.http.open"===p.type){const e="string"==typeof p.streamId?p.streamId:"",i="string"==typeof p.route&&p.route.startsWith("/")?p.route:"/health",r=p.init&&"object"==typeof p.init?p.init:{},s=r.headers&&"object"==typeof r.headers?r.headers:{},a=new AbortController,c=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/http-streams/${encodeURIComponent(e)}`,t})(e),u=new l(c,{headers:d(c)});return o.set(e,{tunnel:u,controller:a}),u.on("open",async()=>{try{const n=await fetch((e=>{const n=e.startsWith("/")?e:`/${e}`,i="function"==typeof t.port?t.port():t.port;return new URL(`/api/node-agent${n}`,`http://127.0.0.1:${i}`)})(i),{method:tr(r.method),headers:{...s,...t.token?{authorization:`Bearer ${t.token}`}:{}},body:"string"==typeof r.body?r.body:void 0,signal:a.signal});if(await m(u,JSON.stringify({type:"node-agent.http.head",streamId:e,status:n.status,headers:Object.fromEntries(n.headers.entries())})),n.body){const e=n.body.getReader();for(;;){const{done:t,value:n}=await e.read();if(t)break;await m(u,Buffer.from(n),!0)}}await m(u,JSON.stringify({type:"node-agent.http.end",streamId:e})),u.close(1e3,"HTTP stream completed.")}catch(t){u.readyState===l.OPEN&&(await m(u,JSON.stringify({type:"node-agent.http.error",streamId:e,message:t instanceof Error?t.message:String(t)})).catch(()=>{}),u.close(1011,"HTTP stream failed."))}finally{o.delete(e)}}),u.on("close",()=>{a.abort(),o.delete(e)}),void u.on("error",()=>a.abort())}if("control-plane.websocket.open"===p.type){const e="string"==typeof p.streamId?p.streamId:"",i="string"==typeof p.route?p.route:"",o=Array.isArray(p.protocols)?p.protocols.filter(e=>"string"==typeof e):void 0;try{const a=t.token?{authorization:`Bearer ${t.token}`}:void 0,u=o?.length?new l(c(i),o,{headers:a}):new l(c(i),{headers:a}),m=(e=>{const t=new URL(n);return t.pathname=`${t.pathname.replace(/\/$/,"")}/streams/${encodeURIComponent(e)}`,t})(e),p=new l(m,{headers:d(m)});s.set(e,{upstream:u,tunnel:p,close:(e=1e3,t="")=>{u.close(e,t),p.close(e,t)}}),u.on("open",()=>{r.send(JSON.stringify({type:"node-agent.websocket.open",streamId:e,protocol:u.protocol}))}),function(e,t,n={}){const i=n.pendingFrameLimit??256;let r=!1,s=vn(t);const o=[],a=[];let c;const d=()=>{c&&(clearTimeout(c),c=void 0)},l=(n,r)=>{if(n.length>=i)return Sn(e,1011,"WebSocket bridge pending frame limit exceeded."),void Sn(t,1011,"WebSocket bridge pending frame limit exceeded.");n.push(r)};n.upstreamOpenTimeoutMs&&!s&&(c=setTimeout(()=>{s||r||(Sn(e,1011,"Upstream websocket did not open."),Sn(t))},n.upstreamOpenTimeoutMs)),e.on("open",()=>_n(e,a)),t.on("open",()=>{d(),s=!0,n.onUpstreamOpen?.(),_n(t,o)}),e.on("message",(e,n=!1)=>{const i={data:e,isBinary:Boolean(n)};vn(t)?En(t,i):l(o,i)}),t.on("message",(t,n=!1)=>{const i={data:t,isBinary:Boolean(n)};vn(e)?En(e,i):l(a,i)}),t.on("close",(t,i)=>{d(),n.onUpstreamClose?.(t,i),(s||r||!n.onUpstreamCloseBeforeOpen?.())&&Sn(e,t,i)}),t.on("error",t=>{n.onUpstreamError?.(t),(s||r||!n.onUpstreamErrorBeforeOpen?.(t))&&Sn(e)}),e.on("close",(e,i)=>{d(),r=!0,n.onClientClose?.(e,i),Sn(t,e,i)}),e.on("error",e=>{d(),r=!0,n.onClientError?.(e),Sn(t,1011,"WebSocket bridge client failed.")})}(p,u,{pendingFrameLimit:256,upstreamOpenTimeoutMs:1e4,onClientClose:()=>{s.delete(e)},onClientError:t=>{s.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))},onUpstreamClose:(t,n)=>{s.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.close",streamId:e,code:"number"==typeof t?t:1e3,reason:Buffer.isBuffer(n)?n.toString("utf8"):String(n||"")}))},onUpstreamError:t=>{s.delete(e),r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}})}catch(t){r.send(JSON.stringify({type:"node-agent.websocket.error",streamId:e,message:t instanceof Error?t.message:String(t)}))}return}if("control-plane.websocket.close"===p.type){const e="string"==typeof p.streamId?p.streamId:"";return void u(e,"number"==typeof p.code?p.code:1e3,"string"==typeof p.reason?p.reason:"")}if("control-plane.request"===p.type){const n="string"==typeof p.requestId?p.requestId:"",i=p.init&&"object"==typeof p.init?p.init:{},s="string"==typeof p.route&&p.route.startsWith("/")?p.route:"/health",o=i.headers&&"object"==typeof i.headers?i.headers:{};try{const a=await e.inject({method:tr(i.method),url:`/api/node-agent${s}`,headers:{...o,...t.token?{authorization:`Bearer ${t.token}`}:{}},payload:"string"==typeof i.body?i.body:void 0});r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:a.statusCode,headers:a.headers,body:a.body}))}catch(e){r.send(JSON.stringify({type:"node-agent.response",requestId:n,status:502,error:{code:"NODE_AGENT_REVERSE_INJECT_FAILED",message:e instanceof Error?e.message:String(e)}}))}}}),r}async function Zs(e){const r=Si(e.dataDir),s=(o=e.host,a=e.port,sn.parse({bindScope:"0.0.0.0"===o.trim()?"all-ipv4":"loopback",port:a}));var o,a;const c=t.existsSync(r.settingsPath),d=function(e,t){return new Di(e.settingsPath,()=>({version:1,externalListener:t}),{schema:ss,sanitize:ws})}(r,s),l=d.get().externalListener,u=function(e,i={}){return function(e,i={}){t.mkdirSync(n.dirname(e),{recursive:!0});const r={pid:process.pid,hostname:g.hostname(),component:i.component,command:process.argv.join(" "),acquiredAt:(new Date).toISOString(),token:m.randomUUID(),dataDir:i.dataDir,host:i.host,port:i.port};for(let n=0;n<5;n+=1)try{return t.mkdirSync(e),t.writeFileSync(Mi(e),`${JSON.stringify({token:r.token,startedAt:(new Date).toISOString()})}\n`,{encoding:"utf8",mode:384,flag:"wx"}),Ui(e,r),{lockPath:e,owner:r,release(){const n=$i(e);n?.token===r.token&&t.rmSync(e,{recursive:!0,force:!0})}}}catch(r){if("EEXIST"!==r.code)throw r;const s=$i(e);if(Fi(s?.pid))throw new ji(e,s,i.error);if(!s&&Bi(e)<2e3){if(n+1<5){qi();continue}throw new ji(e,void 0,i.error)}const o=m.randomUUID();if(!Ki(e,o)){if(n+1<5){qi();continue}throw new ji(e,$i(e),i.error)}const a=$i(e);if(Fi(a?.pid))throw Hi(Li(e)),new ji(e,a,i.error);if(s?.token&&a?.token!==s.token){Hi(Li(e));continue}if(!Ji(e,o))continue;t.rmSync(e,{recursive:!0,force:!0})}const s=$i(e);throw new ji(e,s,i.error)}(e,{...i,component:"node-agent",error:{label:"Node agent",code:"NODE_AGENT_ALREADY_RUNNING"}})}(n.join(g.tmpdir(),`task-handoff-node-agent-${process.getuid?.()??"user"}.lock`),{dataDir:r.dataDir,host:bs(l.bindScope),port:l.port});try{const s={...e,port:l.port},o=await Ws(s),a=function(e,t,n,i){const r=t.token||process.env.TASK_HANDOFF_NODE_AGENT_TOKEN,s=new Yr(n),o=new Map,a=t=>{const n=t.url.replace(/\/$/,"");o.get(n)?.close(1e3,"Reverse tunnel reconnecting.");const s=Xs(e,{tunnelUrl:Ys(t.url),nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r,keyId:t.keyId,secret:t.secret});return o.set(n,s),s.on("close",()=>{o.get(n)===s&&o.delete(n)}),s};return{connect:a,connectConfigured:()=>{const n=function(e){const t=e.controlPlaneTunnelUrl||process.env.TASK_HANDOFF_CONTROL_PLANE_TUNNEL_URL;if(t)return t;const n=process.env.TASK_HANDOFF_CONTROL_PLANE_URL;if(!n)return;const i=new URL("/api/node-agent/tunnel",n);return i.protocol="https:"===i.protocol?"wss:":"ws:",i.toString()}(t);if(n){const a=s.reverseTunnelSecret(process.env.TASK_HANDOFF_CONTROL_PLANE_URL,t.remoteSecret||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_SECRET,t.remoteKeyId||process.env.TASK_HANDOFF_NODE_AGENT_REMOTE_KEY_ID),c=(process.env.TASK_HANDOFF_CONTROL_PLANE_URL||n).replace(/\/$/,"");o.get(c)?.close(1e3,"Reverse tunnel reconnecting.");const d=Xs(e,{tunnelUrl:n,nodeId:i,port:()=>e.nodeAgentState.currentListenerPort,token:r,keyId:a?.keyId,secret:a?.secret});o.set(c,d)}for(const e of s.configuredRemoteControlPlanes())e.url&&!1!==e.active&&a({url:e.url,keyId:e.keyId,secret:e.secret})},closeAll:()=>{for(const e of o.values())e.close(1001,"Node agent shutting down.");o.clear()}}}(o,s,r,new Yr(r).resolveNodeId(e.nodeId||process.env.TASK_HANDOFF_NODE_ID));o.decorate("nodeAgentReverseTunnels",a);const m=new qs({app:o,state:o.nodeAgentState,settings:d,config:l,source:c?"persisted":"bootstrap"});let p;o.decorate("nodeAgentListenerManager",m),function(e){let t=!1;const n=async n=>{if(!t){t=!0,a.closeAll(),p?.close();try{await e.close()}finally{process.exitCode=n?0:process.exitCode}}},i=()=>{n("SIGINT")},r=()=>{n("SIGTERM")};process.once("SIGINT",i),process.once("SIGTERM",r),e.addHook("onClose",async()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(o),o.addHook("onClose",async()=>{p?.close(),u.release()});try{await o.ready();const s=e.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH||Wi(r.dataDir);p=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 m.start(),a.connectConfigured(),await(o.nodeAgentRestoreLocalInstances?.())}catch(e){throw await o.close(),e}}catch(e){throw u.release(),e}}function Qs(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 eo(e){if("local-ipc"!==e&&"local-loopback"!==e)throw new Error("Connection mode must be local-ipc or local-loopback.");return e}function to(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 r=new e.Command;r.name("task-handoff-node-agent").description("Run a TaskHandoff node agent.").version(function(){try{return JSON.parse(t.readFileSync(n.resolve(__dirname,"..","package.json"),"utf8")).version||"unknown"}catch{return"unknown"}}()).option("--host <host>","Node agent host",process.env.TASK_HANDOFF_NODE_AGENT_HOST||"127.0.0.1").option("-p, --port <port>","Node agent port",Qs,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",eo).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 Zs({host:e.host,port:e.port,dataDir:e.dataDir,token:e.token,connectionMode:e.connectionMode,ipcPath:e.ipcPath,controlPlaneTunnelUrl:e.controlPlaneTunnelUrl})}),r.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",to).option("--json","Print raw JSON output").action(async e=>{const t=r.opts(),n=e.ipcPath||t.ipcPath||process.env.TASK_HANDOFF_NODE_AGENT_IPC_PATH,s=e.dataDir||t.dataDir||process.env.TASK_HANDOFF_NODE_AGENT_DATA_DIR,o=e.endpoint?void 0:n||Wi(s||vi()),c=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((c,d)=>{const l=i.request({socketPath:e,method:r,path:`/api/node-agent${t}`,headers:Object.fromEntries(o.entries())},e=>{const t=e.statusCode||500;c(new Response("HEAD"!==r&&204!==t&&205!==t&&304!==t?a.Readable.toWeb(e):null,{status:t,headers:e.headers}))});l.on("error",d);const u=()=>l.destroy(new DOMException("The operation was aborted.","AbortError"));n.signal?.aborted?u():n.signal?.addEventListener("abort",u,{once:!0}),l.once("close",()=>n.signal?.removeEventListener("abort",u)),void 0!==s&&l.write(s),l.end()})}(e.ipcPath,"/pairing/invites",{method:"POST",headers:t,body:n}),s=await 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(c,null,2)):(c.nodeId&&console.log(`Node: ${c.nodeId}`),console.log(`Join token: ${c.joinToken}`),c.expiresAt&&console.log(`Expires: ${c.expiresAt}`))}),await r.parseAsync(process.argv)})().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});
|