@xenosystem/agent-sdk 0.9.21 → 0.9.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +18 -8
  2. package/dist/artifacts/index.cjs +1 -1
  3. package/dist/artifacts/index.js +1 -1
  4. package/dist/automation/index.cjs +16 -3
  5. package/dist/automation/index.d.cts +367 -1
  6. package/dist/automation/index.d.ts +367 -1
  7. package/dist/automation/index.js +16 -3
  8. package/dist/automation/metafile-cjs.json +1 -1
  9. package/dist/automation/metafile-esm.json +1 -1
  10. package/dist/control-plane/index.cjs +1 -1
  11. package/dist/control-plane/index.js +1 -1
  12. package/dist/control-room/index.d.cts +1 -1
  13. package/dist/control-room/index.d.ts +1 -1
  14. package/dist/control-room/metafile-cjs.json +1 -1
  15. package/dist/control-room/metafile-esm.json +1 -1
  16. package/dist/coordination/index.cjs +2 -0
  17. package/dist/coordination/index.d.cts +395 -0
  18. package/dist/coordination/index.d.ts +395 -0
  19. package/dist/coordination/index.js +2 -0
  20. package/dist/coordination/metafile-cjs.json +1 -0
  21. package/dist/coordination/metafile-esm.json +1 -0
  22. package/dist/electron/index.cjs +123 -119
  23. package/dist/electron/index.d.cts +61 -0
  24. package/dist/electron/index.d.ts +61 -0
  25. package/dist/electron/index.js +118 -114
  26. package/dist/electron/metafile-cjs.json +1 -1
  27. package/dist/electron/metafile-esm.json +1 -1
  28. package/dist/governance/index.d.cts +29 -0
  29. package/dist/governance/index.d.ts +29 -0
  30. package/dist/hosted/index.cjs +1 -1
  31. package/dist/hosted/index.js +1 -1
  32. package/dist/hosted/metafile-cjs.json +1 -1
  33. package/dist/hosted/metafile-esm.json +1 -1
  34. package/dist/index.cjs +359 -351
  35. package/dist/index.d.cts +1964 -1254
  36. package/dist/index.d.ts +1964 -1254
  37. package/dist/index.js +359 -351
  38. package/dist/mcp/index.d.cts +28 -0
  39. package/dist/mcp/index.d.ts +28 -0
  40. package/dist/metafile-cjs.json +1 -1
  41. package/dist/metafile-esm.json +1 -1
  42. package/dist/providers/metafile-cjs.json +1 -1
  43. package/dist/providers/metafile-esm.json +1 -1
  44. package/dist/session/index.cjs +56 -54
  45. package/dist/session/index.d.cts +69 -1
  46. package/dist/session/index.d.ts +69 -1
  47. package/dist/session/index.js +56 -54
  48. package/dist/session/metafile-cjs.json +1 -1
  49. package/dist/session/metafile-esm.json +1 -1
  50. package/dist/skills/index.d.cts +28 -0
  51. package/dist/skills/index.d.ts +28 -0
  52. package/dist/ui/index.d.cts +28 -0
  53. package/dist/ui/index.d.ts +28 -0
  54. package/dist/utils/index.cjs +17 -16
  55. package/dist/utils/index.d.cts +31 -1
  56. package/dist/utils/index.d.ts +31 -1
  57. package/dist/utils/index.js +14 -13
  58. package/dist/utils/metafile-cjs.json +1 -1
  59. package/dist/utils/metafile-esm.json +1 -1
  60. package/package.json +6 -1
@@ -0,0 +1,395 @@
1
+ declare const XENO_COORDINATION_SCHEMA_VERSION: 1;
2
+ type XenoGoalStatus = "active" | "paused" | "waiting" | "blocked" | "completed" | "failed" | "cancelled";
3
+ type XenoGoalTaskStatus = "pending" | "ready" | "running" | "blocked" | "failed" | "completed" | "cancelled" | "interrupted";
4
+ interface XenoGoalCriterion {
5
+ id: string;
6
+ description: string;
7
+ required: boolean;
8
+ }
9
+ interface XenoGoalCriterionResult {
10
+ criterionId: string;
11
+ satisfied: boolean;
12
+ evidence: string[];
13
+ reason: string;
14
+ evaluatedAt: string;
15
+ }
16
+ interface XenoGoalVerification {
17
+ status: "pending" | "running" | "passed" | "failed";
18
+ criteria: XenoGoalCriterionResult[];
19
+ evidence: string[];
20
+ summary?: string;
21
+ verifiedAt?: string;
22
+ verifiedBy?: string;
23
+ }
24
+ interface XenoGoalTask {
25
+ id: string;
26
+ milestoneId: string;
27
+ parentTaskId?: string;
28
+ title: string;
29
+ description?: string;
30
+ status: XenoGoalTaskStatus;
31
+ assignedAgentId?: string;
32
+ dependsOn?: string[];
33
+ progress?: string;
34
+ resultEventId?: string;
35
+ createdAt: string;
36
+ updatedAt: string;
37
+ completedAt?: string;
38
+ }
39
+ interface XenoGoalMilestone {
40
+ id: string;
41
+ title: string;
42
+ description?: string;
43
+ status: "pending" | "active" | "blocked" | "completed" | "cancelled";
44
+ taskIds: string[];
45
+ createdAt: string;
46
+ updatedAt: string;
47
+ completedAt?: string;
48
+ }
49
+ interface XenoGoalProgress {
50
+ summary: string;
51
+ currentMilestoneId?: string;
52
+ currentTaskId?: string;
53
+ completedTaskCount: number;
54
+ totalTaskCount: number;
55
+ percent?: number;
56
+ outstanding: string[];
57
+ decisions: string[];
58
+ updatedAt: string;
59
+ }
60
+ interface XenoGoalRecord {
61
+ schemaVersion: typeof XENO_COORDINATION_SCHEMA_VERSION;
62
+ id: string;
63
+ version: number;
64
+ sessionId: string;
65
+ objective: string;
66
+ why?: string;
67
+ successCriteria: XenoGoalCriterion[];
68
+ constraints: string[];
69
+ limits?: {
70
+ maxIterations?: number;
71
+ maxTokens?: number;
72
+ maxWallClockMs?: number;
73
+ };
74
+ metadata: Record<string, string | number | boolean>;
75
+ status: XenoGoalStatus;
76
+ milestones: XenoGoalMilestone[];
77
+ tasks: XenoGoalTask[];
78
+ progress: XenoGoalProgress;
79
+ verification: XenoGoalVerification;
80
+ steering: Array<{
81
+ id: string;
82
+ instruction: string;
83
+ createdAt: string;
84
+ consumedAt?: string;
85
+ }>;
86
+ createdAt: string;
87
+ updatedAt: string;
88
+ completedAt?: string;
89
+ }
90
+ type XenoLoopKind = "agentic-development" | "goal-continuation" | "scheduled";
91
+ type XenoLoopStatus = "running" | "paused" | "waiting" | "stopped" | "completed" | "failed";
92
+ interface XenoLoopSchedule {
93
+ kind: "fixed-interval" | "dynamic";
94
+ intervalMs?: number;
95
+ nextRunAt?: string;
96
+ expiresAt?: string;
97
+ }
98
+ interface XenoLoopIteration {
99
+ number: number;
100
+ startedAt: string;
101
+ completedAt?: string;
102
+ status: "running" | "completed" | "failed" | "interrupted";
103
+ activity: string;
104
+ taskId?: string;
105
+ verificationEventId?: string;
106
+ error?: string;
107
+ }
108
+ interface XenoLoopRecord {
109
+ schemaVersion: typeof XENO_COORDINATION_SCHEMA_VERSION;
110
+ id: string;
111
+ version: number;
112
+ sessionId: string;
113
+ goalId?: string;
114
+ kind: XenoLoopKind;
115
+ status: XenoLoopStatus;
116
+ currentActivity?: string;
117
+ iterations: XenoLoopIteration[];
118
+ schedule?: XenoLoopSchedule;
119
+ stopReason?: string;
120
+ createdAt: string;
121
+ updatedAt: string;
122
+ stoppedAt?: string;
123
+ }
124
+ type XenoHandoffStatus = "prepared" | "available" | "claimed" | "completed" | "failed" | "cancelled";
125
+ interface XenoHandoffOperation {
126
+ operationId: string;
127
+ kind: "tool" | "command" | "build" | "subagent" | "other";
128
+ status: "running" | "completed" | "interrupted";
129
+ sideEffecting: boolean;
130
+ recovery: "waited" | "resume" | "retry" | "manual";
131
+ }
132
+ interface XenoHandoffRecord {
133
+ schemaVersion: typeof XENO_COORDINATION_SCHEMA_VERSION;
134
+ id: string;
135
+ version: number;
136
+ sessionId: string;
137
+ goalId?: string;
138
+ loopId?: string;
139
+ status: XenoHandoffStatus;
140
+ sourceOwnerId: string;
141
+ targetOwnerId?: string;
142
+ claimedBy?: string;
143
+ sourceLeaseEpoch: number;
144
+ targetLeaseEpoch?: number;
145
+ workspace?: string;
146
+ branch?: string;
147
+ currentMilestoneId?: string;
148
+ currentTaskId?: string;
149
+ agentIds: string[];
150
+ operations: XenoHandoffOperation[];
151
+ contextDigest?: string;
152
+ createdAt: string;
153
+ updatedAt: string;
154
+ claimedAt?: string;
155
+ completedAt?: string;
156
+ failedAt?: string;
157
+ failureReason?: string;
158
+ }
159
+ interface XenoExecutionOwner {
160
+ ownerId: string;
161
+ leaseId: string;
162
+ epoch: number;
163
+ acquiredAt: string;
164
+ heartbeatAt: string;
165
+ expiresAt: string;
166
+ processId?: number;
167
+ host?: string;
168
+ }
169
+ type XenoCoordinationEventType = "goal.created" | "goal.updated" | "goal.steered" | "goal.completed" | "goal.cancelled" | "loop.started" | "loop.iteration" | "loop.paused" | "loop.waiting" | "loop.resumed" | "loop.stopped" | "loop.completed" | "loop.failed" | "handoff.created" | "handoff.claimed" | "handoff.completed" | "handoff.failed" | "ownership.acquired" | "ownership.renewed" | "ownership.released";
170
+ interface XenoCoordinationEvent {
171
+ schemaVersion: typeof XENO_COORDINATION_SCHEMA_VERSION;
172
+ id: string;
173
+ sequence: number;
174
+ type: XenoCoordinationEventType;
175
+ sessionId: string;
176
+ goalId?: string;
177
+ loopId?: string;
178
+ handoffId?: string;
179
+ ownerId?: string;
180
+ timestamp: string;
181
+ data: Record<string, unknown>;
182
+ }
183
+ interface XenoCoordinationSessionState {
184
+ schemaVersion: typeof XENO_COORDINATION_SCHEMA_VERSION;
185
+ sessionId: string;
186
+ version: number;
187
+ ownershipEpoch: number;
188
+ owner?: XenoExecutionOwner;
189
+ goals: XenoGoalRecord[];
190
+ loops: XenoLoopRecord[];
191
+ handoffs: XenoHandoffRecord[];
192
+ events: XenoCoordinationEvent[];
193
+ createdAt: string;
194
+ updatedAt: string;
195
+ }
196
+ interface XenoCoordinationStoreOptions {
197
+ rootDirectory?: string;
198
+ now?: () => string;
199
+ idFactory?: (prefix: string) => string;
200
+ ownerLeaseMs?: number;
201
+ lockTimeoutMs?: number;
202
+ lockStaleMs?: number;
203
+ maximumEventsPerSession?: number;
204
+ }
205
+ interface CreateXenoGoalInput {
206
+ sessionId: string;
207
+ objective: string;
208
+ why?: string;
209
+ successCriteria?: Array<string | Omit<XenoGoalCriterion, "id"> & {
210
+ id?: string;
211
+ }>;
212
+ constraints?: string[];
213
+ limits?: XenoGoalRecord["limits"];
214
+ metadata?: Record<string, string | number | boolean>;
215
+ }
216
+ interface CreateXenoHandoffInput {
217
+ sessionId: string;
218
+ sourceOwnerId: string;
219
+ sourceLeaseId: string;
220
+ goalId?: string;
221
+ loopId?: string;
222
+ targetOwnerId?: string;
223
+ workspace?: string;
224
+ branch?: string;
225
+ currentMilestoneId?: string;
226
+ currentTaskId?: string;
227
+ agentIds?: string[];
228
+ operations?: XenoHandoffOperation[];
229
+ contextDigest?: string;
230
+ }
231
+ declare class XenoCoordinationError extends Error {
232
+ readonly code: "INVALID" | "NOT_FOUND" | "CONFLICT" | "NOT_OWNER" | "LEASE_EXPIRED" | "UNSAFE_HANDOFF" | "VERIFICATION_REQUIRED";
233
+ readonly details: Record<string, unknown>;
234
+ constructor(code: "INVALID" | "NOT_FOUND" | "CONFLICT" | "NOT_OWNER" | "LEASE_EXPIRED" | "UNSAFE_HANDOFF" | "VERIFICATION_REQUIRED", message: string, details?: Record<string, unknown>);
235
+ }
236
+ interface UpdateXenoGoalInput {
237
+ objective?: string;
238
+ why?: string;
239
+ constraints?: string[];
240
+ successCriteria?: XenoGoalCriterion[];
241
+ status?: Exclude<XenoGoalStatus, "completed">;
242
+ progress?: Partial<Omit<XenoGoalProgress, "updatedAt">>;
243
+ verification?: XenoGoalVerification;
244
+ metadata?: Record<string, string | number | boolean>;
245
+ }
246
+ interface StartXenoLoopInput {
247
+ sessionId: string;
248
+ goalId?: string;
249
+ kind: XenoLoopKind;
250
+ activity?: string;
251
+ schedule?: XenoLoopSchedule;
252
+ }
253
+ interface ClaimXenoHandoffInput {
254
+ sessionId: string;
255
+ handoffId: string;
256
+ targetOwnerId: string;
257
+ processId?: number;
258
+ host?: string;
259
+ }
260
+ declare class DurableXenoCoordinationStore {
261
+ private readonly rootDirectory;
262
+ private readonly now;
263
+ private readonly idFactory;
264
+ private readonly ownerLeaseMs;
265
+ private readonly lockTimeoutMs;
266
+ private readonly lockStaleMs;
267
+ private readonly maximumEventsPerSession;
268
+ constructor(options?: XenoCoordinationStoreOptions);
269
+ getSessionState(sessionId: string): Promise<XenoCoordinationSessionState>;
270
+ listSessionStates(): Promise<XenoCoordinationSessionState[]>;
271
+ createGoal(input: CreateXenoGoalInput): Promise<XenoGoalRecord>;
272
+ getGoal(sessionId: string, goalId?: string): Promise<XenoGoalRecord | undefined>;
273
+ updateGoal(sessionId: string, goalId: string, expectedVersion: number, update: UpdateXenoGoalInput): Promise<XenoGoalRecord>;
274
+ addMilestone(sessionId: string, goalId: string, expectedVersion: number, input: {
275
+ title: string;
276
+ description?: string;
277
+ }): Promise<XenoGoalRecord>;
278
+ addTask(sessionId: string, goalId: string, expectedVersion: number, input: {
279
+ milestoneId: string;
280
+ parentTaskId?: string;
281
+ title: string;
282
+ description?: string;
283
+ assignedAgentId?: string;
284
+ dependsOn?: string[];
285
+ }): Promise<XenoGoalRecord>;
286
+ updateTask(sessionId: string, goalId: string, taskId: string, expectedVersion: number, update: Pick<XenoGoalTask, "status"> & Partial<Pick<XenoGoalTask, "progress" | "resultEventId" | "assignedAgentId">>): Promise<XenoGoalRecord>;
287
+ steerGoal(sessionId: string, goalId: string, expectedVersion: number, instruction: string): Promise<XenoGoalRecord>;
288
+ consumeGoalSteering(sessionId: string, goalId: string, expectedVersion: number): Promise<{
289
+ goal: XenoGoalRecord;
290
+ instructions: Array<{
291
+ id: string;
292
+ instruction: string;
293
+ createdAt: string;
294
+ }>;
295
+ }>;
296
+ completeGoal(sessionId: string, goalId: string, expectedVersion: number, verification: XenoGoalVerification): Promise<XenoGoalRecord>;
297
+ cancelGoal(sessionId: string, goalId: string, expectedVersion: number, reason: string): Promise<XenoGoalRecord>;
298
+ startLoop(input: StartXenoLoopInput): Promise<XenoLoopRecord>;
299
+ getLoop(sessionId: string, loopId?: string): Promise<XenoLoopRecord | undefined>;
300
+ beginLoopIteration(sessionId: string, loopId: string, expectedVersion: number, activity: string, taskId?: string): Promise<XenoLoopRecord>;
301
+ finishLoopIteration(sessionId: string, loopId: string, expectedVersion: number, result: {
302
+ status: "completed" | "failed" | "interrupted";
303
+ verificationEventId?: string;
304
+ error?: string;
305
+ nextStatus?: Extract<XenoLoopStatus, "running" | "waiting" | "failed">;
306
+ }): Promise<XenoLoopRecord>;
307
+ setLoopStatus(sessionId: string, loopId: string, expectedVersion: number, status: Extract<XenoLoopStatus, "paused" | "running" | "waiting" | "stopped" | "completed" | "failed">, reason?: string): Promise<XenoLoopRecord>;
308
+ acquireOwnership(sessionId: string, ownerId: string, options?: {
309
+ processId?: number;
310
+ host?: string;
311
+ leaseMs?: number;
312
+ }): Promise<XenoExecutionOwner>;
313
+ renewOwnership(sessionId: string, ownerId: string, leaseId: string, leaseMs?: number): Promise<XenoExecutionOwner>;
314
+ releaseOwnership(sessionId: string, ownerId: string, leaseId: string): Promise<XenoExecutionOwner>;
315
+ createHandoff(input: CreateXenoHandoffInput): Promise<XenoHandoffRecord>;
316
+ claimHandoff(input: ClaimXenoHandoffInput): Promise<{
317
+ handoff: XenoHandoffRecord;
318
+ owner: XenoExecutionOwner;
319
+ }>;
320
+ completeHandoff(sessionId: string, handoffId: string, ownerId: string, leaseId: string): Promise<XenoHandoffRecord>;
321
+ failHandoff(sessionId: string, handoffId: string, reason: string): Promise<XenoHandoffRecord>;
322
+ private mutateGoal;
323
+ private mutateLoop;
324
+ private recalculateProgress;
325
+ private requireGoal;
326
+ private requireOwner;
327
+ private assertVersion;
328
+ private newOwner;
329
+ private ownerExpired;
330
+ private appendEvent;
331
+ private mutate;
332
+ private statePath;
333
+ private lockPath;
334
+ private readState;
335
+ private writeState;
336
+ private renameReplacing;
337
+ private withSessionLock;
338
+ private staleLockOwner;
339
+ private quarantineLock;
340
+ }
341
+ type XenoCoordinationAction = "state.get" | "goal.create" | "goal.update" | "goal.complete" | "goal.cancel" | "goal.steer" | "loop.start" | "loop.get" | "loop.begin" | "loop.finish" | "loop.set_status" | "ownership.acquire" | "ownership.renew" | "ownership.release" | "handoff.create" | "handoff.claim" | "handoff.complete" | "handoff.fail";
342
+ interface ExecuteXenoCoordinationActionInput {
343
+ action: XenoCoordinationAction;
344
+ sessionId: string;
345
+ payload?: Record<string, unknown>;
346
+ }
347
+ interface ExecuteXenoCoordinationActionResult {
348
+ action: XenoCoordinationAction;
349
+ sessionId: string;
350
+ result: unknown;
351
+ state: XenoCoordinationSessionState;
352
+ event?: XenoCoordinationEvent;
353
+ }
354
+ declare function executeXenoCoordinationAction(store: DurableXenoCoordinationStore, input: ExecuteXenoCoordinationActionInput): Promise<ExecuteXenoCoordinationActionResult>;
355
+ interface XenoExecutionLeaseSessionOptions {
356
+ store?: DurableXenoCoordinationStore;
357
+ sessionId: string;
358
+ ownerId?: string;
359
+ processId?: number;
360
+ host?: string;
361
+ leaseMs?: number;
362
+ heartbeatMs?: number;
363
+ claimHandoffId?: string;
364
+ onOwnershipLost?: (error: unknown) => void;
365
+ }
366
+ declare class XenoExecutionLeaseSession {
367
+ readonly sessionId: string;
368
+ readonly ownerId: string;
369
+ private readonly store;
370
+ private readonly processId;
371
+ private readonly host;
372
+ private readonly leaseMs;
373
+ private readonly heartbeatMs;
374
+ private readonly claimHandoffId?;
375
+ private readonly onOwnershipLost?;
376
+ private timer?;
377
+ private heartbeatInFlight;
378
+ private owner?;
379
+ private stopped;
380
+ private lostError?;
381
+ private preparedHandoffId?;
382
+ constructor(options: XenoExecutionLeaseSessionOptions);
383
+ get currentOwner(): XenoExecutionOwner | undefined;
384
+ get active(): boolean;
385
+ start(): Promise<XenoExecutionOwner>;
386
+ assertOwned(): Promise<XenoExecutionOwner>;
387
+ private renewHeldLease;
388
+ prepareHandoff(input?: Omit<CreateXenoHandoffInput, "sessionId" | "sourceOwnerId" | "sourceLeaseId">): Promise<XenoHandoffRecord>;
389
+ stop(options?: {
390
+ release?: boolean;
391
+ }): Promise<void>;
392
+ private heartbeat;
393
+ private markLost;
394
+ }
395
+ export { type ClaimXenoHandoffInput, type CreateXenoGoalInput, type CreateXenoHandoffInput, DurableXenoCoordinationStore, type ExecuteXenoCoordinationActionInput, type ExecuteXenoCoordinationActionResult, type StartXenoLoopInput, type UpdateXenoGoalInput, XENO_COORDINATION_SCHEMA_VERSION, type XenoCoordinationAction, XenoCoordinationError, type XenoCoordinationEvent, type XenoCoordinationEventType, type XenoCoordinationSessionState, type XenoCoordinationStoreOptions, XenoExecutionLeaseSession, type XenoExecutionLeaseSessionOptions, type XenoExecutionOwner, type XenoGoalCriterion, type XenoGoalCriterionResult, type XenoGoalMilestone, type XenoGoalProgress, type XenoGoalRecord, type XenoGoalStatus, type XenoGoalTask, type XenoGoalTaskStatus, type XenoGoalVerification, type XenoHandoffOperation, type XenoHandoffRecord, type XenoHandoffStatus, type XenoLoopIteration, type XenoLoopKind, type XenoLoopRecord, type XenoLoopSchedule, type XenoLoopStatus, executeXenoCoordinationAction };
@@ -0,0 +1,2 @@
1
+ var I=1,p=class extends Error{constructor(s,r,e={}){super(r);this.code=s;this.details=e;this.name="XenoCoordinationError"}code;details};import{createHash as D,randomUUID as X}from"node:crypto";import*as f from"node:fs/promises";import*as A from"node:os";import*as m from"node:path";import{homedir as L,platform as P,release as _}from"node:os";import{resolve as x}from"node:path";var ee=P();var te=_(),ne=L();function N(){let d=process.env.XENO_AGENT_HOME?.trim();return d?x(d):x(L(),".xeno-agent")}var F=3e4,H=3e4,$=6e4,V=2e4,b=new Set(["EACCES","EBUSY","EPERM"]),T=[5,10,20,40,80,160,320],q=[5,10,20,40,80,160,320];function u(d,t,s=16384){let r=d.trim();if(!r||r.length>s)throw new p("INVALID",`${t} must be non-empty and no longer than ${s} characters`);return r}function k(d,t){return[...new Set((d??[]).map(s=>u(s,t)))]}function U(d){if(!d)return;let t={};for(let[s,r]of Object.entries(d))if(r!==void 0){if(!Number.isSafeInteger(r)||r<=0)throw new p("INVALID",`${s} must be a positive safe integer when provided`);t[s]=r}return t}function j(d){if(d){if(d.kind!=="fixed-interval"&&d.kind!=="dynamic")throw new p("INVALID","schedule.kind must be fixed-interval or dynamic");if(d.kind==="fixed-interval"&&(!Number.isSafeInteger(d.intervalMs)||(d.intervalMs??0)<=0))throw new p("INVALID","Fixed-interval schedules require a positive safe intervalMs");if(d.intervalMs!==void 0&&(!Number.isSafeInteger(d.intervalMs)||d.intervalMs<=0))throw new p("INVALID","schedule.intervalMs must be a positive safe integer when provided");for(let t of["nextRunAt","expiresAt"]){let s=d[t];if(s!==void 0&&!Number.isFinite(Date.parse(s)))throw new p("INVALID",`schedule.${t} must be an ISO timestamp when provided`)}return w(d)}}function w(d){return structuredClone(d)}function E(d){let t=Date.parse(d);return Number.isFinite(t)?t:0}function R(d){if(!Number.isInteger(d)||d<=0)return!1;try{return process.kill(d,0),!0}catch(t){return t.code==="EPERM"}}function J(d){return{summary:"Goal created; work has not started.",completedTaskCount:0,totalTaskCount:0,outstanding:[],decisions:[],updatedAt:d}}function B(){return{status:"pending",criteria:[],evidence:[]}}function W(d){return D("sha256").update(d).digest("hex")}var S=class{rootDirectory;now;idFactory;ownerLeaseMs;lockTimeoutMs;lockStaleMs;maximumEventsPerSession;constructor(t={}){this.rootDirectory=t.rootDirectory??m.join(N(),"coordination"),this.now=t.now??(()=>new Date().toISOString()),this.idFactory=t.idFactory??(s=>`${s}_${X()}`),this.ownerLeaseMs=t.ownerLeaseMs??F,this.lockTimeoutMs=t.lockTimeoutMs??H,this.lockStaleMs=t.lockStaleMs??$,this.maximumEventsPerSession=t.maximumEventsPerSession??V}async getSessionState(t){let s=u(t,"sessionId",1024);return w(await this.readState(s))}async listSessionStates(){let t=m.join(this.rootDirectory,"sessions"),s;try{s=await f.readdir(t)}catch(e){if(e.code==="ENOENT")return[];throw e}return(await Promise.all(s.filter(e=>e.endsWith(".json")).map(async e=>{try{let n=JSON.parse(await f.readFile(m.join(t,e),"utf8"));return n.schemaVersion!==1||typeof n.sessionId!="string"?void 0:((!Number.isSafeInteger(n.ownershipEpoch)||n.ownershipEpoch<0)&&(n.ownershipEpoch=Math.max(n.owner?.epoch??0,...n.handoffs.map(o=>o.targetLeaseEpoch??o.sourceLeaseEpoch??0))),n)}catch{return}}))).filter(e=>e!==void 0).sort((e,n)=>E(n.updatedAt)-E(e.updatedAt)).map(e=>w(e))}async createGoal(t){let s=u(t.sessionId,"sessionId",1024),r=U(t.limits);return this.mutate(s,e=>{let n=e.goals.find(c=>["active","paused","waiting","blocked"].includes(c.status));if(n)throw new p("CONFLICT",`Session ${s} already has active goal ${n.id}`);let o=this.now(),i=(t.successCriteria??[]).map(c=>typeof c=="string"?{id:this.idFactory("criterion"),description:u(c,"successCriteria"),required:!0}:{id:c.id?u(c.id,"successCriteria.id",512):this.idFactory("criterion"),description:u(c.description,"successCriteria.description"),required:c.required}),a={schemaVersion:1,id:this.idFactory("goal"),version:1,sessionId:s,objective:u(t.objective,"objective"),...t.why?{why:u(t.why,"why")}:{},successCriteria:i,constraints:k(t.constraints,"constraints"),...r?{limits:r}:{},metadata:w(t.metadata??{}),status:"active",milestones:[],tasks:[],progress:J(o),verification:B(),steering:[],createdAt:o,updatedAt:o};return e.goals.push(a),this.appendEvent(e,"goal.created",{goalId:a.id,data:{objective:a.objective}}),a})}async getGoal(t,s){let r=await this.getSessionState(t),e=s?r.goals.find(n=>n.id===s):[...r.goals].reverse().find(n=>["active","paused","waiting","blocked"].includes(n.status));return e?w(e):void 0}async updateGoal(t,s,r,e){return this.mutate(t,n=>{let o=this.requireGoal(n,s);if(this.assertVersion(o.id,o.version,r),["completed","cancelled","failed"].includes(o.status))throw new p("CONFLICT",`Goal ${o.id} is terminal (${o.status})`);return e.status==="active"&&o.status==="blocked"?o.status="active":e.status&&(o.status=e.status),e.objective!==void 0&&(o.objective=u(e.objective,"objective")),e.why!==void 0&&(o.why=u(e.why,"why")),e.constraints&&(o.constraints=k(e.constraints,"constraints")),e.successCriteria&&(o.successCriteria=w(e.successCriteria)),e.progress&&(o.progress={...o.progress,...w(e.progress),outstanding:k(e.progress.outstanding??o.progress.outstanding,"progress.outstanding"),decisions:k(e.progress.decisions??o.progress.decisions,"progress.decisions"),updatedAt:this.now()}),e.verification&&(o.verification=w(e.verification)),e.metadata&&(o.metadata=w(e.metadata)),o.version+=1,o.updatedAt=this.now(),this.appendEvent(n,"goal.updated",{goalId:o.id,data:{status:o.status,version:o.version}}),o})}async addMilestone(t,s,r,e){return this.mutateGoal(t,s,r,(n,o)=>{let i={id:this.idFactory("milestone"),title:u(e.title,"milestone.title"),...e.description?{description:u(e.description,"milestone.description")}:{},status:n.milestones.some(a=>a.status==="active")?"pending":"active",taskIds:[],createdAt:o,updatedAt:o};n.milestones.push(i),n.progress.currentMilestoneId??=i.id,n.progress.updatedAt=o})}async addTask(t,s,r,e){return this.mutateGoal(t,s,r,(n,o)=>{let i=n.milestones.find(l=>l.id===e.milestoneId);if(!i)throw new p("NOT_FOUND",`Milestone ${e.milestoneId} was not found`);if(e.parentTaskId&&!n.tasks.some(l=>l.id===e.parentTaskId))throw new p("NOT_FOUND",`Parent task ${e.parentTaskId} was not found`);let a=[...new Set(e.dependsOn??[])];for(let l of a)if(!n.tasks.some(g=>g.id===l))throw new p("NOT_FOUND",`Task dependency ${l} was not found`);let c={id:this.idFactory("task"),milestoneId:i.id,...e.parentTaskId?{parentTaskId:e.parentTaskId}:{},title:u(e.title,"task.title"),...e.description?{description:u(e.description,"task.description")}:{},status:a.length===0?"ready":"pending",...e.assignedAgentId?{assignedAgentId:u(e.assignedAgentId,"task.assignedAgentId",512)}:{},...a.length?{dependsOn:a}:{},createdAt:o,updatedAt:o};n.tasks.push(c),i.taskIds.push(c.id),i.updatedAt=o,n.progress.totalTaskCount=n.tasks.length,n.progress.outstanding=n.tasks.filter(l=>l.status!=="completed").map(l=>l.title),n.progress.updatedAt=o})}async updateTask(t,s,r,e,n){return this.mutateGoal(t,s,e,(o,i)=>{let a=o.tasks.find(l=>l.id===r);if(!a)throw new p("NOT_FOUND",`Task ${r} was not found`);a.status=n.status,n.progress!==void 0&&(a.progress=u(n.progress,"task.progress")),n.resultEventId!==void 0&&(a.resultEventId=u(n.resultEventId,"task.resultEventId",512)),n.assignedAgentId!==void 0&&(a.assignedAgentId=u(n.assignedAgentId,"task.assignedAgentId",512)),a.updatedAt=i,a.status==="completed"&&(a.completedAt=i);let c=o.milestones.find(l=>l.id===a.milestoneId);if(c){let l=o.tasks.filter(g=>g.milestoneId===c.id);l.length>0&&l.every(g=>g.status==="completed")?(c.status="completed",c.completedAt=i):l.some(g=>g.status==="running")?c.status="active":l.some(g=>g.status==="blocked")&&(c.status="blocked"),c.updatedAt=i}for(let l of o.tasks)l.status!=="pending"||!l.dependsOn?.length||l.dependsOn.every(g=>o.tasks.find(y=>y.id===g)?.status==="completed")&&(l.status="ready",l.updatedAt=i);this.recalculateProgress(o,i)})}async steerGoal(t,s,r,e){return this.mutateGoal(t,s,r,(n,o,i)=>{let a=this.idFactory("steer");n.steering.push({id:a,instruction:u(e,"instruction"),createdAt:o}),this.appendEvent(i,"goal.steered",{goalId:s,data:{steeringId:a}})},!1)}async consumeGoalSteering(t,s,r){let e=[];return{goal:await this.mutateGoal(t,s,r,(o,i)=>{e=o.steering.filter(a=>!a.consumedAt).map(({id:a,instruction:c,createdAt:l})=>({id:a,instruction:c,createdAt:l}));for(let a of o.steering)a.consumedAt||(a.consumedAt=i)}),instructions:e}}async completeGoal(t,s,r,e){if(e.status!=="passed")throw new p("VERIFICATION_REQUIRED","Goal completion requires passed verification");return this.mutate(t,n=>{let o=this.requireGoal(n,s);this.assertVersion(o.id,o.version,r);let i=o.successCriteria.filter(l=>l.required),a=i.filter(l=>{let g=e.criteria.find(y=>y.criterionId===l.id);return!g?.satisfied||g.evidence.length===0});if(a.length>0)throw new p("VERIFICATION_REQUIRED","Required success criteria lack passing evidence",{unmetCriteria:a.map(l=>l.id)});if(i.length===0&&e.evidence.length===0)throw new p("VERIFICATION_REQUIRED","Goal completion requires at least one durable evidence reference");let c=this.now();return o.status="completed",o.verification=w(e),o.verification.verifiedAt??=c,o.completedAt=c,o.updatedAt=c,o.version+=1,this.appendEvent(n,"goal.completed",{goalId:s,data:{evidence:o.verification.evidence}}),o})}async cancelGoal(t,s,r,e){return this.mutate(t,n=>{let o=this.requireGoal(n,s);if(this.assertVersion(o.id,o.version,r),["completed","cancelled","failed"].includes(o.status))return o;o.status="cancelled",o.updatedAt=this.now(),o.version+=1,this.appendEvent(n,"goal.cancelled",{goalId:s,data:{reason:u(e,"reason")}});for(let i of n.loops.filter(a=>a.goalId===s&&["running","paused","waiting"].includes(a.status)))i.status="stopped",i.stopReason=`Goal cancelled: ${e}`,i.stoppedAt=this.now(),i.updatedAt=i.stoppedAt,i.version+=1;return o})}async startLoop(t){return this.mutate(t.sessionId,s=>{if(t.kind==="goal-continuation"&&!t.goalId)throw new p("INVALID","Goal-continuation loops require a goalId");if(t.goalId){let i=this.requireGoal(s,t.goalId);if(["completed","cancelled","failed"].includes(i.status))throw new p("CONFLICT",`Cannot start a loop for terminal goal ${i.id}`)}if(t.kind==="scheduled"&&!t.schedule)throw new p("INVALID","Scheduled loops require schedule metadata");if(t.kind!=="scheduled"&&t.schedule)throw new p("INVALID","Only scheduled loops may carry schedule metadata");let r=j(t.schedule),e=s.loops.find(i=>i.goalId===t.goalId&&i.kind===t.kind&&["running","paused","waiting"].includes(i.status));if(e)throw new p("CONFLICT",`Loop ${e.id} is already active`);let n=this.now(),o={schemaVersion:1,id:this.idFactory("loop"),version:1,sessionId:s.sessionId,...t.goalId?{goalId:t.goalId}:{},kind:t.kind,status:"running",...t.activity?{currentActivity:u(t.activity,"activity")}:{},iterations:[],...r?{schedule:r}:{},createdAt:n,updatedAt:n};return s.loops.push(o),this.appendEvent(s,"loop.started",{loopId:o.id,goalId:o.goalId,data:{kind:o.kind}}),o})}async getLoop(t,s){let r=await this.getSessionState(t),e=s?r.loops.find(n=>n.id===s):[...r.loops].reverse().find(n=>["running","paused","waiting"].includes(n.status));return e?w(e):void 0}async beginLoopIteration(t,s,r,e,n){return this.mutateLoop(t,s,r,(o,i,a)=>{if(o.status!=="running")throw new p("CONFLICT",`Loop ${o.id} is ${o.status}`);if(o.iterations.some(l=>l.status==="running"))throw new p("CONFLICT",`Loop ${o.id} already has a running iteration`);let c=(o.iterations.at(-1)?.number??0)+1;o.currentActivity=u(e,"activity"),o.iterations.push({number:c,startedAt:i,status:"running",activity:o.currentActivity,...n?{taskId:u(n,"taskId",512)}:{}}),this.appendEvent(a,"loop.iteration",{loopId:s,goalId:o.goalId,data:{number:c,phase:"started",activity:o.currentActivity}})},!1)}async finishLoopIteration(t,s,r,e){return this.mutateLoop(t,s,r,(n,o,i)=>{let a=[...n.iterations].reverse().find(c=>c.status==="running");if(!a)throw new p("CONFLICT",`Loop ${n.id} has no running iteration`);a.status=e.status,a.completedAt=o,e.verificationEventId&&(a.verificationEventId=u(e.verificationEventId,"verificationEventId",512)),e.error&&(a.error=u(e.error,"error")),n.status=e.nextStatus??(n.status==="paused"||n.status==="waiting"?n.status:"running"),this.appendEvent(i,"loop.iteration",{loopId:s,goalId:n.goalId,data:{number:a.number,phase:"finished",status:e.status}})},!1)}async setLoopStatus(t,s,r,e,n){return this.mutateLoop(t,s,r,(o,i,a)=>{let c=o.status;if(["stopped","completed","failed"].includes(c))throw new p("CONFLICT",`Loop ${o.id} is terminal (${c})`);let l=[...o.iterations].reverse().find(y=>y.status==="running");if(l&&e==="completed")throw new p("CONFLICT",`Loop ${o.id} cannot complete while iteration ${l.number} is running`);l&&(e==="stopped"||e==="failed")&&(l.status=e==="failed"?"failed":"interrupted",l.completedAt=i,l.error=u(n??e,"reason")),o.status=e,["stopped","completed","failed"].includes(e)&&(o.stoppedAt=i,o.stopReason=u(n??e,"reason"));let g=e==="paused"?"loop.paused":e==="waiting"?"loop.waiting":e==="running"&&(c==="paused"||c==="waiting")?"loop.resumed":e==="completed"?"loop.completed":e==="failed"?"loop.failed":"loop.stopped";this.appendEvent(a,g,{loopId:s,goalId:o.goalId,data:{previous:c,status:e,...n?{reason:n}:{}}})},!1)}async acquireOwnership(t,s,r={}){return this.mutate(t,e=>{let n=this.now();if(e.owner&&!this.ownerExpired(e.owner,n)){if(e.owner.ownerId===s&&r.processId!==void 0&&e.owner.processId===r.processId&&(r.host===void 0||e.owner.host===r.host))return e.owner;throw new p("CONFLICT",`Session ${t} is owned by ${e.owner.ownerId}`,{owner:e.owner})}let o=e.owner&&this.ownerExpired(e.owner,n)?e.owner:void 0;if(o&&o.ownerId!==s)for(let c of e.handoffs.filter(l=>l.status==="claimed"&&l.claimedBy===o.ownerId))c.status="failed",c.failureReason=`Claimed owner ${o.ownerId} lost its execution lease before completing the handoff.`,c.failedAt=n,c.updatedAt=n,c.version+=1,this.appendEvent(e,"handoff.failed",{handoffId:c.id,goalId:c.goalId,loopId:c.loopId,data:{reason:c.failureReason,expiredLeaseId:o.leaseId}});let i=e.ownershipEpoch+1,a=this.newOwner(s,i,r,n);return e.owner=a,e.ownershipEpoch=i,this.appendEvent(e,"ownership.acquired",{ownerId:s,data:{epoch:i,leaseId:a.leaseId}}),a})}async renewOwnership(t,s,r,e=this.ownerLeaseMs){return this.mutate(t,n=>{let o=this.requireOwner(n,s,r);if(this.ownerExpired(o,this.now()))throw new p("LEASE_EXPIRED",`Ownership lease ${r} expired`);return o.heartbeatAt=this.now(),o.expiresAt=new Date(E(o.heartbeatAt)+e).toISOString(),this.appendEvent(n,"ownership.renewed",{ownerId:s,data:{epoch:o.epoch,leaseId:r}}),o})}async releaseOwnership(t,s,r){return this.mutate(t,e=>{let n=this.requireOwner(e,s,r);return e.owner=void 0,this.appendEvent(e,"ownership.released",{ownerId:s,data:{epoch:n.epoch}}),n})}async createHandoff(t){return this.mutate(t.sessionId,s=>{let r=this.requireOwner(s,t.sourceOwnerId,t.sourceLeaseId);if(this.ownerExpired(r,this.now()))throw new p("LEASE_EXPIRED",`Ownership lease ${r.leaseId} expired`);let e=(t.operations??[]).filter(a=>a.status==="running"&&a.sideEffecting&&a.recovery==="retry");if(e.length>0)throw new p("UNSAFE_HANDOFF","Running side-effecting operations cannot be transferred with automatic retry",{operationIds:e.map(a=>a.operationId)});if(t.goalId&&this.requireGoal(s,t.goalId),t.loopId&&!s.loops.some(a=>a.id===t.loopId))throw new p("NOT_FOUND",`Loop ${t.loopId} was not found`);let n=s.handoffs.find(a=>["prepared","available","claimed"].includes(a.status));if(n)throw new p("CONFLICT",`Handoff ${n.id} is already active`);let o=this.now(),i={schemaVersion:1,id:this.idFactory("handoff"),version:1,sessionId:s.sessionId,...t.goalId?{goalId:t.goalId}:{},...t.loopId?{loopId:t.loopId}:{},status:"available",sourceOwnerId:r.ownerId,...t.targetOwnerId?{targetOwnerId:u(t.targetOwnerId,"targetOwnerId",512)}:{},sourceLeaseEpoch:r.epoch,...t.workspace?{workspace:u(t.workspace,"workspace",32768)}:{},...t.branch?{branch:u(t.branch,"branch",1024)}:{},...t.currentMilestoneId?{currentMilestoneId:t.currentMilestoneId}:{},...t.currentTaskId?{currentTaskId:t.currentTaskId}:{},agentIds:[...new Set(t.agentIds??[])],operations:w(t.operations??[]),...t.contextDigest?{contextDigest:u(t.contextDigest,"contextDigest",512)}:{},createdAt:o,updatedAt:o};return s.handoffs.push(i),this.appendEvent(s,"handoff.created",{handoffId:i.id,goalId:i.goalId,loopId:i.loopId,ownerId:r.ownerId,data:{targetOwnerId:i.targetOwnerId}}),i})}async claimHandoff(t){let s;return{handoff:await this.mutate(t.sessionId,e=>{let n=e.handoffs.find(a=>a.id===t.handoffId);if(!n)throw new p("NOT_FOUND",`Handoff ${t.handoffId} was not found`);if(n.status!=="available")throw new p("CONFLICT",`Handoff ${n.id} is ${n.status}`,{claimedBy:n.claimedBy});if(n.targetOwnerId&&n.targetOwnerId!==t.targetOwnerId)throw new p("CONFLICT",`Handoff ${n.id} is reserved for ${n.targetOwnerId}`);let o=e.owner;if(!o||o.ownerId!==n.sourceOwnerId||o.epoch!==n.sourceLeaseEpoch)throw new p("CONFLICT",`Handoff ${n.id} no longer matches the source ownership epoch`);let i=this.now();return s=this.newOwner(t.targetOwnerId,o.epoch+1,{processId:t.processId,host:t.host},i),e.owner=s,e.ownershipEpoch=s.epoch,n.status="claimed",n.claimedBy=t.targetOwnerId,n.targetOwnerId=t.targetOwnerId,n.targetLeaseEpoch=s.epoch,n.claimedAt=i,n.updatedAt=i,n.version+=1,this.appendEvent(e,"handoff.claimed",{handoffId:n.id,goalId:n.goalId,loopId:n.loopId,ownerId:t.targetOwnerId,data:{sourceOwnerId:n.sourceOwnerId,epoch:s.epoch}}),n}),owner:w(s)}}async completeHandoff(t,s,r,e){return this.mutate(t,n=>{this.requireOwner(n,r,e);let o=n.handoffs.find(i=>i.id===s);if(!o)throw new p("NOT_FOUND",`Handoff ${s} was not found`);if(o.status!=="claimed"||o.claimedBy!==r)throw new p("CONFLICT",`Handoff ${o.id} cannot be completed by ${r}`);return o.status="completed",o.completedAt=this.now(),o.updatedAt=o.completedAt,o.version+=1,this.appendEvent(n,"handoff.completed",{handoffId:s,goalId:o.goalId,loopId:o.loopId,ownerId:r,data:{epoch:n.owner?.epoch}}),o})}async failHandoff(t,s,r){return this.mutate(t,e=>{let n=e.handoffs.find(o=>o.id===s);if(!n)throw new p("NOT_FOUND",`Handoff ${s} was not found`);return["completed","cancelled","failed"].includes(n.status)||(n.status="failed",n.failureReason=u(r,"reason"),n.failedAt=this.now(),n.updatedAt=n.failedAt,n.version+=1,this.appendEvent(e,"handoff.failed",{handoffId:s,goalId:n.goalId,loopId:n.loopId,data:{reason:n.failureReason}})),n})}async mutateGoal(t,s,r,e,n=!0){return this.mutate(t,o=>{let i=this.requireGoal(o,s);this.assertVersion(i.id,i.version,r);let a=this.now();return e(i,a,o),i.version+=1,i.updatedAt=a,n&&this.appendEvent(o,"goal.updated",{goalId:s,data:{status:i.status,version:i.version}}),i})}async mutateLoop(t,s,r,e,n=!0){return this.mutate(t,o=>{let i=o.loops.find(c=>c.id===s);if(!i)throw new p("NOT_FOUND",`Loop ${s} was not found`);this.assertVersion(i.id,i.version,r);let a=this.now();return e(i,a,o),i.version+=1,i.updatedAt=a,n&&this.appendEvent(o,"loop.iteration",{loopId:s,goalId:i.goalId,data:{status:i.status,version:i.version}}),i})}recalculateProgress(t,s){let r=t.tasks.filter(e=>e.status==="completed").length;t.progress.completedTaskCount=r,t.progress.totalTaskCount=t.tasks.length,t.progress.percent=t.tasks.length?Math.round(r/t.tasks.length*100):void 0,t.progress.outstanding=t.tasks.filter(e=>!["completed","cancelled"].includes(e.status)).map(e=>e.title),t.progress.updatedAt=s}requireGoal(t,s){let r=t.goals.find(e=>e.id===s);if(!r)throw new p("NOT_FOUND",`Goal ${s} was not found`);return r}requireOwner(t,s,r){let e=t.owner;if(!e||e.ownerId!==s||e.leaseId!==r)throw new p("NOT_OWNER",`${s} does not own session ${t.sessionId}`,{owner:e});return e}assertVersion(t,s,r){if(!Number.isInteger(r)||r<1||s!==r)throw new p("CONFLICT",`Expected ${t} version ${r}, found ${s}`,{expected:r,actual:s})}newOwner(t,s,r,e){let n=r.leaseMs??this.ownerLeaseMs;if(!Number.isSafeInteger(n)||n<1)throw new p("INVALID","leaseMs must be a positive safe integer");return{ownerId:u(t,"ownerId",512),leaseId:this.idFactory("owner"),epoch:s,acquiredAt:e,heartbeatAt:e,expiresAt:new Date(E(e)+n).toISOString(),...r.processId!==void 0?{processId:r.processId}:{},...r.host?{host:u(r.host,"host",512)}:{}}}ownerExpired(t,s){return E(t.expiresAt)<=E(s)?!0:t.processId!==void 0&&t.host===A.hostname()&&!R(t.processId)}appendEvent(t,s,r){let e={schemaVersion:1,id:this.idFactory("event"),sequence:(t.events.at(-1)?.sequence??0)+1,type:s,sessionId:t.sessionId,...r.goalId?{goalId:r.goalId}:{},...r.loopId?{loopId:r.loopId}:{},...r.handoffId?{handoffId:r.handoffId}:{},...r.ownerId?{ownerId:r.ownerId}:{},timestamp:this.now(),data:w(r.data)};t.events.push(e),t.events.length>this.maximumEventsPerSession&&t.events.splice(0,t.events.length-this.maximumEventsPerSession)}async mutate(t,s){let r=u(t,"sessionId",1024);return this.withSessionLock(r,async()=>{let e=await this.readState(r),n=s(e);return e.version+=1,e.updatedAt=this.now(),await this.writeState(e),w(n)})}statePath(t){return m.join(this.rootDirectory,"sessions",`${W(t)}.json`)}lockPath(t){return`${this.statePath(t)}.lock`}async readState(t){let s=this.statePath(t);try{let r=await f.readFile(s,"utf8"),e=JSON.parse(r);if(e.schemaVersion!==1||e.sessionId!==t)throw new p("INVALID",`Coordination state at ${s} does not match session ${t}`);return(!Number.isSafeInteger(e.ownershipEpoch)||e.ownershipEpoch<0)&&(e.ownershipEpoch=Math.max(e.owner?.epoch??0,...e.handoffs.map(n=>n.targetLeaseEpoch??n.sourceLeaseEpoch??0))),e}catch(r){if(r.code!=="ENOENT")throw r;let e=this.now();return{schemaVersion:1,sessionId:t,version:0,ownershipEpoch:0,goals:[],loops:[],handoffs:[],events:[],createdAt:e,updatedAt:e}}}async writeState(t){let s=this.statePath(t.sessionId),r=m.dirname(s);await f.mkdir(r,{recursive:!0});let e=`${s}.${process.pid}.${X()}.tmp`,n=await f.open(e,"wx");try{await n.writeFile(`${JSON.stringify(t,null,2)}
2
+ `,"utf8"),await n.sync()}finally{await n.close()}try{await this.renameReplacing(e,s);try{let o=await f.open(r,"r");try{await o.sync()}finally{await o.close()}}catch{}}finally{await f.unlink(e).catch(()=>{})}}async renameReplacing(t,s){for(let r=0;;r+=1)try{await f.rename(t,s);return}catch(e){let n=e.code,o=T[r];if(process.platform!=="win32"||!n||!b.has(n)||o===void 0)throw e;await new Promise(i=>setTimeout(i,o))}}async withSessionLock(t,s){let r=this.lockPath(t),e=m.join(r,"owner.json"),n=X(),o=`${r}.candidate.${n}`,i=Date.now();await f.mkdir(m.dirname(r),{recursive:!0});let a={schemaVersion:1,token:n,pid:process.pid,host:A.hostname(),acquiredAt:this.now()};await f.mkdir(o),await f.writeFile(m.join(o,"owner.json"),JSON.stringify(a),{encoding:"utf8",flag:"wx"});for(let c=0;;c+=1)try{await f.rename(o,r);break}catch(l){let g=l.code;if(!(g==="EEXIST"||process.platform==="win32"&&!!g&&b.has(g)))throw await f.rm(o,{recursive:!0,force:!0}).catch(()=>{}),l;let C=await this.staleLockOwner(r,e);if(C){await this.quarantineLock(r,C.token,"stale");continue}if(Date.now()-i>=this.lockTimeoutMs)throw await f.rm(o,{recursive:!0,force:!0}).catch(()=>{}),new p("CONFLICT",`Timed out waiting for coordination lock for session ${t}`);await new Promise(M=>setTimeout(M,Math.min(100,5+c*5)+Math.floor(Math.random()*10)))}try{return await s()}finally{await this.quarantineLock(r,n,"released"),await f.rm(o,{recursive:!0,force:!0}).catch(()=>{})}}async staleLockOwner(t,s){try{let[r,e]=await Promise.all([f.readFile(s,"utf8").catch(()=>""),f.stat(t)]),n=r?JSON.parse(r):void 0;return!n||n.host===A.hostname()&&R(n.pid)?void 0:Date.now()-e.mtimeMs>this.lockStaleMs?n:void 0}catch{return}}async quarantineLock(t,s,r){let e=m.join(t,"owner.json"),n=`${t}.${r}.${s}.${X()}`;for(let o=0;;o+=1){let i;try{i=JSON.parse(await f.readFile(e,"utf8"))}catch(a){if(a.code==="ENOENT")return;throw a}if(i.token!==s)return;try{await f.rename(t,n);break}catch(a){let c=a.code;if(c==="ENOENT"||c==="EEXIST")return;let l=T[o];if(process.platform!=="win32"||!c||!b.has(c)||l===void 0)throw a;await new Promise(g=>setTimeout(g,l))}}for(let o=0;;o+=1)try{await f.rm(n,{recursive:!0});return}catch(i){let a=i.code;if(a==="ENOENT")return;let c=q[o];if(process.platform!=="win32"||!a||!b.has(a)||c===void 0)throw i;await new Promise(l=>setTimeout(l,c))}}};function O(d,t){if(!d||typeof d!="object"||Array.isArray(d))throw new Error(`${t} must be an object`);return d}function h(d,t){if(typeof d!="string"||!d.trim())throw new Error(`${t} must be a non-empty string`);return d}function v(d,t){if(typeof d!="number"||!Number.isInteger(d))throw new Error(`${t} must be an integer`);return d}async function de(d,t){let{action:s,sessionId:r}=t,e=t.payload??{},n;switch(s){case"state.get":n=await d.getSessionState(r);break;case"goal.create":n=await d.createGoal({sessionId:r,...e});break;case"goal.update":n=await d.updateGoal(r,h(e.goalId,"goalId"),v(e.expectedVersion,"expectedVersion"),O(e.update,"update"));break;case"goal.complete":n=await d.completeGoal(r,h(e.goalId,"goalId"),v(e.expectedVersion,"expectedVersion"),O(e.verification,"verification"));break;case"goal.cancel":n=await d.cancelGoal(r,h(e.goalId,"goalId"),v(e.expectedVersion,"expectedVersion"),h(e.reason,"reason"));break;case"goal.steer":n=await d.steerGoal(r,h(e.goalId,"goalId"),v(e.expectedVersion,"expectedVersion"),h(e.instruction,"instruction"));break;case"loop.start":n=await d.startLoop({sessionId:r,kind:h(e.kind,"kind"),...typeof e.goalId=="string"?{goalId:e.goalId}:{},...typeof e.activity=="string"?{activity:e.activity}:{},...e.schedule?{schedule:O(e.schedule,"schedule")}:{}});break;case"loop.get":n=await d.getLoop(r,typeof e.loopId=="string"?e.loopId:void 0);break;case"loop.begin":n=await d.beginLoopIteration(r,h(e.loopId,"loopId"),v(e.expectedVersion,"expectedVersion"),h(e.activity,"activity"),typeof e.taskId=="string"?e.taskId:void 0);break;case"loop.finish":n=await d.finishLoopIteration(r,h(e.loopId,"loopId"),v(e.expectedVersion,"expectedVersion"),O(e.result,"result"));break;case"loop.set_status":n=await d.setLoopStatus(r,h(e.loopId,"loopId"),v(e.expectedVersion,"expectedVersion"),h(e.status,"status"),typeof e.reason=="string"?e.reason:void 0);break;case"ownership.acquire":n=await d.acquireOwnership(r,h(e.ownerId,"ownerId"),O(e.options??{},"options"));break;case"ownership.renew":n=await d.renewOwnership(r,h(e.ownerId,"ownerId"),h(e.leaseId,"leaseId"),typeof e.leaseMs=="number"?e.leaseMs:void 0);break;case"ownership.release":n=await d.releaseOwnership(r,h(e.ownerId,"ownerId"),h(e.leaseId,"leaseId"));break;case"handoff.create":n=await d.createHandoff({sessionId:r,...e});break;case"handoff.claim":n=await d.claimHandoff({sessionId:r,handoffId:h(e.handoffId,"handoffId"),targetOwnerId:h(e.targetOwnerId,"targetOwnerId"),...typeof e.processId=="number"?{processId:e.processId}:{},...typeof e.host=="string"?{host:e.host}:{}});break;case"handoff.complete":n=await d.completeHandoff(r,h(e.handoffId,"handoffId"),h(e.ownerId,"ownerId"),h(e.leaseId,"leaseId"));break;case"handoff.fail":n=await d.failHandoff(r,h(e.handoffId,"handoffId"),h(e.reason,"reason"));break}let o=await d.getSessionState(r),i=s==="state.get"||s==="loop.get"?void 0:o.events.at(-1);return{action:s,sessionId:r,result:n,state:o,...i?{event:i}:{}}}import{randomUUID as K}from"node:crypto";import{hostname as Q}from"node:os";var G=class{sessionId;ownerId;store;processId;host;leaseMs;heartbeatMs;claimHandoffId;onOwnershipLost;timer;heartbeatInFlight=!1;owner;stopped=!1;lostError;preparedHandoffId;constructor(t){if(this.store=t.store??new S,this.sessionId=t.sessionId,this.processId=t.processId??process.pid,this.host=t.host??Q(),this.ownerId=t.ownerId??`runtime:${this.host}:${this.processId}:${K().slice(0,8)}`,this.leaseMs=t.leaseMs??3e4,this.heartbeatMs=t.heartbeatMs??Math.max(250,Math.floor(this.leaseMs/3)),this.heartbeatMs>=this.leaseMs)throw new Error("heartbeatMs must be shorter than leaseMs");this.claimHandoffId=t.claimHandoffId,this.onOwnershipLost=t.onOwnershipLost}get currentOwner(){return this.owner?structuredClone(this.owner):void 0}get active(){return!!this.owner&&!this.stopped&&this.lostError===void 0}async start(){if(this.owner)return structuredClone(this.owner);if(this.stopped)throw new Error("Execution lease session has already stopped");if(this.claimHandoffId){let t=await this.store.claimHandoff({sessionId:this.sessionId,handoffId:this.claimHandoffId,targetOwnerId:this.ownerId,processId:this.processId,host:this.host});this.owner=t.owner,await this.store.completeHandoff(this.sessionId,this.claimHandoffId,this.ownerId,this.owner.leaseId)}else this.owner=await this.store.acquireOwnership(this.sessionId,this.ownerId,{processId:this.processId,host:this.host,leaseMs:this.leaseMs});return this.timer=setInterval(()=>{this.heartbeat()},this.heartbeatMs),this.timer.unref?.(),structuredClone(this.owner)}async assertOwned(){if(this.stopped)throw new Error("Execution surface is detached");if(this.lostError)throw this.lostError;if(this.preparedHandoffId)throw new Error(`Execution surface prepared handoff ${this.preparedHandoffId} and is detached from mutation`);if(!this.owner)throw new Error("Execution ownership was not started");return this.renewHeldLease()}async renewHeldLease(){if(!this.owner)throw new Error("Execution ownership was not started");try{return this.owner=await this.store.renewOwnership(this.sessionId,this.ownerId,this.owner.leaseId,this.leaseMs),structuredClone(this.owner)}catch(t){throw this.markLost(t),t}}async prepareHandoff(t={}){if(this.preparedHandoffId)throw new Error(`Handoff ${this.preparedHandoffId} is already prepared`);let s=await this.assertOwned(),r=await this.store.createHandoff({...t,sessionId:this.sessionId,sourceOwnerId:s.ownerId,sourceLeaseId:s.leaseId});return this.preparedHandoffId=r.id,r}async stop(t={}){if(this.stopped)return;this.stopped=!0,this.timer&&clearInterval(this.timer),this.timer=void 0;let s=this.owner;if(this.owner=void 0,!(t.release===!1||this.preparedHandoffId||!s||this.lostError))try{await this.store.releaseOwnership(this.sessionId,s.ownerId,s.leaseId)}catch{}}async heartbeat(){if(!(!this.active||this.heartbeatInFlight)){this.heartbeatInFlight=!0;try{await this.renewHeldLease()}catch(t){this.markLost(t)}finally{this.heartbeatInFlight=!1}}}markLost(t){this.lostError===void 0&&(this.lostError=t,this.timer&&clearInterval(this.timer),this.timer=void 0,this.onOwnershipLost?.(t))}};export{S as DurableXenoCoordinationStore,I as XENO_COORDINATION_SCHEMA_VERSION,p as XenoCoordinationError,G as XenoExecutionLeaseSession,de as executeXenoCoordinationAction};
@@ -0,0 +1 @@
1
+ {"inputs":{"src/coordination/types.ts":{"bytes":7186,"imports":[],"format":"esm"},"src/utils/platform.ts":{"bytes":5600,"imports":[{"path":"node:os","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true}],"format":"esm"},"src/coordination/store.ts":{"bytes":50651,"imports":[{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:fs/promises","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"src/utils/platform.ts","kind":"import-statement","original":"../utils/platform.js"},{"path":"src/coordination/types.ts","kind":"import-statement","original":"./types.js"}],"format":"esm"},"src/coordination/runtime.ts":{"bytes":6174,"imports":[{"path":"./store.js","kind":"import-statement","external":true}],"format":"esm"},"src/coordination/lease.ts":{"bytes":5947,"imports":[{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true},{"path":"src/coordination/store.ts","kind":"import-statement","original":"./store.js"}],"format":"esm"},"src/coordination/index.ts":{"bytes":114,"imports":[{"path":"src/coordination/types.ts","kind":"import-statement","original":"./types.js"},{"path":"src/coordination/store.ts","kind":"import-statement","original":"./store.js"},{"path":"src/coordination/runtime.ts","kind":"import-statement","original":"./runtime.js"},{"path":"src/coordination/lease.ts","kind":"import-statement","original":"./lease.js"}],"format":"esm"}},"outputs":{"dist/coordination/index.cjs":{"imports":[{"path":"node:crypto","kind":"require-call","external":true},{"path":"node:fs/promises","kind":"require-call","external":true},{"path":"node:os","kind":"require-call","external":true},{"path":"node:path","kind":"require-call","external":true},{"path":"node:os","kind":"require-call","external":true},{"path":"node:path","kind":"require-call","external":true},{"path":"node:crypto","kind":"require-call","external":true},{"path":"node:os","kind":"require-call","external":true}],"exports":[],"entryPoint":"src/coordination/index.ts","inputs":{"src/coordination/index.ts":{"bytesInOutput":210},"src/coordination/types.ts":{"bytesInOutput":136},"src/coordination/store.ts":{"bytesInOutput":23981},"src/utils/platform.ts":{"bytesInOutput":240},"src/coordination/runtime.ts":{"bytesInOutput":2957},"src/coordination/lease.ts":{"bytesInOutput":3143}},"bytes":31400}}}
@@ -0,0 +1 @@
1
+ {"inputs":{"src/coordination/types.ts":{"bytes":7186,"imports":[],"format":"esm"},"src/utils/platform.ts":{"bytes":5600,"imports":[{"path":"node:os","kind":"import-statement","external":true},{"path":"node:child_process","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true}],"format":"esm"},"src/coordination/store.ts":{"bytes":50651,"imports":[{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:fs/promises","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"src/utils/platform.ts","kind":"import-statement","original":"../utils/platform.js"},{"path":"src/coordination/types.ts","kind":"import-statement","original":"./types.js"}],"format":"esm"},"src/coordination/runtime.ts":{"bytes":6174,"imports":[{"path":"./store.js","kind":"import-statement","external":true}],"format":"esm"},"src/coordination/lease.ts":{"bytes":5947,"imports":[{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true},{"path":"src/coordination/store.ts","kind":"import-statement","original":"./store.js"}],"format":"esm"},"src/coordination/index.ts":{"bytes":114,"imports":[{"path":"src/coordination/types.ts","kind":"import-statement","original":"./types.js"},{"path":"src/coordination/store.ts","kind":"import-statement","original":"./store.js"},{"path":"src/coordination/runtime.ts","kind":"import-statement","original":"./runtime.js"},{"path":"src/coordination/lease.ts","kind":"import-statement","original":"./lease.js"}],"format":"esm"}},"outputs":{"dist/coordination/index.js":{"imports":[{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:fs/promises","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"node:crypto","kind":"import-statement","external":true},{"path":"node:os","kind":"import-statement","external":true}],"exports":["DurableXenoCoordinationStore","XENO_COORDINATION_SCHEMA_VERSION","XenoCoordinationError","XenoExecutionLeaseSession","executeXenoCoordinationAction"],"entryPoint":"src/coordination/index.ts","inputs":{"src/coordination/types.ts":{"bytesInOutput":136},"src/coordination/index.ts":{"bytesInOutput":0},"src/coordination/store.ts":{"bytesInOutput":23927},"src/utils/platform.ts":{"bytesInOutput":216},"src/coordination/runtime.ts":{"bytesInOutput":2957},"src/coordination/lease.ts":{"bytesInOutput":3141}},"bytes":30552}}}