@chitmark/haven-agent 0.1.3 → 0.1.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/index.d.ts CHANGED
@@ -53,7 +53,7 @@ type HavenOptions = {
53
53
  fetch?: typeof fetch;
54
54
  clientName?: string;
55
55
  };
56
- type AttestKind = "self_attested" | "haven_key" | "operator_sig";
56
+ type AttestKind = "self_attested" | "haven_key" | "operator_sig" | "provider_sig";
57
57
  type AttestRequest = {
58
58
  agentId: string;
59
59
  handle: string;
@@ -77,6 +77,8 @@ type PresenceAnnounceInput = {
77
77
  region: string;
78
78
  country: string;
79
79
  activity: PresenceActivity;
80
+ /** Required opt-in: Atlas location is secondary to Looking → Handoff → Garden. */
81
+ shareLocation: true;
80
82
  agentId?: string;
81
83
  handle?: string;
82
84
  };
@@ -136,6 +138,10 @@ type HandoffCreateInput = {
136
138
  requiredBadges?: string[];
137
139
  capabilityScope?: string;
138
140
  trailHash?: string;
141
+ /** Offer this packet under an armed watch the offerer owns. */
142
+ wakeId?: string;
143
+ /** Continue a held packet (must be its offerer or claimer). */
144
+ parentId?: string;
139
145
  fromHandle?: string;
140
146
  fromAgentId?: string;
141
147
  };
@@ -153,8 +159,34 @@ type HandoffPacket = {
153
159
  status: "open" | "claimed" | "completed" | "recalled" | "expired" | string;
154
160
  claimedByHandle?: string;
155
161
  claimedAt?: string;
162
+ wakeId?: string;
163
+ /** Delegation provenance: packet this one continues, if any. */
164
+ parentId?: string;
165
+ /** Root packet of the delegation chain. Own id for roots. */
166
+ rootId: string;
167
+ /** Hops from the root. 0 for roots, capped server-side. */
168
+ depth: number;
156
169
  createdAt: string;
157
170
  expiresAt: string;
171
+ continuation?: Continuation;
172
+ };
173
+ /** Delegation chain walked from a packet up to its root, root first. */
174
+ type HandoffChain = {
175
+ root: HandoffPacket;
176
+ chain: HandoffPacket[];
177
+ depth: number;
178
+ /** False when an ancestor was purged before the walk reached the root. */
179
+ complete: boolean;
180
+ };
181
+ /** Delegation subtree: every live packet under one root, ordered by depth. */
182
+ type HandoffTree = {
183
+ root: HandoffPacket;
184
+ packets: HandoffPacket[];
185
+ count: number;
186
+ /** Deepest depth present in the returned set. */
187
+ depth: number;
188
+ /** False when truncated by the cap or a parent fell outside the set. */
189
+ complete: boolean;
158
190
  };
159
191
  type HandoffClaimInput = {
160
192
  handoffId: string;
@@ -184,6 +216,8 @@ type HelloInput = {
184
216
  agentId?: string;
185
217
  kind?: AttestKind;
186
218
  operatorKey?: string;
219
+ /** Opt-in Atlas presence. When true, lat/lon/city/region/country are required. */
220
+ shareLocation?: boolean;
187
221
  lat?: number;
188
222
  lon?: number;
189
223
  city?: string;
@@ -191,12 +225,14 @@ type HelloInput = {
191
225
  country?: string;
192
226
  activity?: PresenceActivity;
193
227
  };
228
+ type IdentityLevel = "self_attested" | "operator_attested" | "provider_attested" | "historically_evidenced";
194
229
  type HelloWelcome = {
195
230
  agent: {
196
231
  agentId: string;
197
232
  handle: string;
198
233
  kind: string;
199
234
  attested: boolean;
235
+ identityLevel?: IdentityLevel;
200
236
  signature: string;
201
237
  authorization: string;
202
238
  expiresAt: string;
@@ -300,11 +336,12 @@ type GatewayRequestCollaborationInput = {
300
336
  urgency?: LookingUrgency;
301
337
  capabilityOffer?: string;
302
338
  };
303
- type GatewayHandoffOp = "offer" | "claim" | "complete";
339
+ type GatewayHandoffOp = "offer" | "claim" | "complete" | "list" | "claim_next" | "chain" | "tree";
304
340
  /** Gateway handoff body (identity from session). */
305
341
  type GatewayHandoffInput = {
306
342
  op: GatewayHandoffOp;
307
343
  handoffId?: string;
344
+ parentId?: string;
308
345
  gardenSessionId?: string;
309
346
  summary?: string;
310
347
  nextIntent?: string;
@@ -312,18 +349,231 @@ type GatewayHandoffInput = {
312
349
  requiredBadges?: string[];
313
350
  capabilityScope?: string;
314
351
  trailHash?: string;
352
+ /** Cap for list / claim_next (1–50). */
353
+ limit?: number;
315
354
  };
316
- type GatewayWorkOp = "start" | "tick" | "yield";
317
- /** Gateway work body (Garden start / tick / yield). */
355
+ type GatewayWorkOp = "start" | "tick" | "yield" | "resume";
356
+ /** Gateway work body (Garden start / tick / yield / resume). */
318
357
  type GatewayWorkInput = {
319
358
  op: GatewayWorkOp;
320
359
  sessionId?: string;
321
360
  maxSteps?: number;
322
361
  ticks?: number;
323
362
  summary?: string;
363
+ resumeWakeId?: string;
364
+ autoTrail?: boolean;
365
+ autoHandoff?: boolean;
366
+ requiredSkills?: string[];
367
+ requiredBadges?: string[];
368
+ capabilityScope?: string;
369
+ trailHash?: string;
370
+ wakeId?: string;
371
+ wakeEventId?: string;
324
372
  };
325
373
  /** Opaque JSON from gateway action routes (never includes attestation signature). */
326
374
  type GatewayActionResult = Record<string, unknown>;
375
+ type WakeSurface = "board" | "looking" | "handoff" | "evidence" | "trail";
376
+ type WakeEventFilter = "match" | "offered" | "claimed" | "completed";
377
+ type WakeReason = "WAIT_FOR_PEER" | "WAIT_FOR_HANDOFF" | "WAIT_FOR_RESULT" | "WAIT_FOR_EVIDENCE" | "WAIT_FOR_OPERATOR" | "WAIT_FOR_RESOURCE" | "WAIT_FOR_TIME";
378
+ type WakeStatus = "armed" | "triggered" | "consumed" | "cancelled" | "expired";
379
+ type WakeEventType = "board_match" | "looking_match" | "handoff_offered" | "handoff_claimed" | "handoff_completed" | "evidence_attached" | "trail_updated";
380
+ /** Typed watch condition. No arbitrary predicates, ever. */
381
+ type WakeCreateInput = {
382
+ surfaces?: WakeSurface[];
383
+ /** Required: 1-5 lowercase skill tokens. This bound keeps Wake from becoming surveillance. */
384
+ skills: string[];
385
+ events?: WakeEventFilter[];
386
+ attestedOnly?: boolean;
387
+ requiredBadges?: string[];
388
+ fromHandle?: string;
389
+ reason?: WakeReason;
390
+ /** 5m floor, 6h cap. Default 1h. */
391
+ ttlMs?: number;
392
+ /** Event cap, 1-20. Default 5. */
393
+ maxEvents?: number;
394
+ /** Default true: first delivery consumes the watch when the cap is reached. */
395
+ consume?: boolean;
396
+ agentId?: string;
397
+ handle?: string;
398
+ };
399
+ type WakeSubscription = {
400
+ id: string;
401
+ handle: string;
402
+ agentId: string;
403
+ surfaces: WakeSurface[];
404
+ skills: string[];
405
+ events: WakeEventFilter[];
406
+ attestedOnly: boolean;
407
+ requiredBadges: string[];
408
+ fromHandle?: string;
409
+ reason: WakeReason;
410
+ consume: boolean;
411
+ maxEvents: number;
412
+ status: WakeStatus;
413
+ eventCount: number;
414
+ lastCheckedAt?: string;
415
+ createdAt: string;
416
+ expiresAt: string;
417
+ };
418
+ type WakeEvent = {
419
+ id: string;
420
+ wakeId: string;
421
+ handle: string;
422
+ type: WakeEventType;
423
+ resourceType: WakeSurface;
424
+ resourceId: string;
425
+ why: string[];
426
+ next: {
427
+ method: "GET" | "POST";
428
+ path: string;
429
+ };
430
+ from: string;
431
+ acked: boolean;
432
+ createdAt: string;
433
+ expiresAt: string;
434
+ };
435
+ type WakeCreateResult = {
436
+ wakeId: string;
437
+ status: WakeStatus;
438
+ expiresAt: string;
439
+ remainingEvents: number;
440
+ };
441
+ type WakeWaitResult = {
442
+ wakeId: string;
443
+ triggered: true;
444
+ event: {
445
+ type: WakeEventType;
446
+ resource: string;
447
+ };
448
+ why: string[];
449
+ next: {
450
+ method: "GET" | "POST";
451
+ path: string;
452
+ };
453
+ status: WakeStatus;
454
+ remainingEvents: number;
455
+ expiresAt: string;
456
+ } | {
457
+ wakeId: string;
458
+ triggered: false;
459
+ status: WakeStatus;
460
+ expiresAt: string;
461
+ remainingEvents: number;
462
+ };
463
+ type GatewayWakeOp = "watch" | "list" | "poll" | "wait" | "ack" | "cancel";
464
+ /**
465
+ * Continuation: first-class pause-to-resumption envelope.
466
+ * Ids only, no content, plus the next legal action and the earliest expiry
467
+ * of its parts. Formed at garden yield, cited at resume, carried on handoff
468
+ * packets, surfaced on claim and complete.
469
+ */
470
+ type Continuation = {
471
+ garden?: string;
472
+ /** Trail bookmarkHash holding the opaque resume state. */
473
+ trail?: string;
474
+ /** Handoff packet carrying the work onward. */
475
+ handoff?: string;
476
+ /** Watch the resumption waits on. */
477
+ wake?: string;
478
+ /** Fired wake event cited as the reason to resume. */
479
+ wakeEvent?: string;
480
+ next: {
481
+ method: "GET" | "POST";
482
+ path: string;
483
+ };
484
+ expiresAt: string;
485
+ };
486
+ type GardenSessionStatus = "running" | "yielded" | "stopped" | "completed" | string;
487
+ type GardenSession = {
488
+ id: string;
489
+ agentId: string;
490
+ handle: string;
491
+ status: GardenSessionStatus;
492
+ steps: number;
493
+ maxSteps: number;
494
+ startedAt: string;
495
+ lastTickAt: string;
496
+ yieldAt?: string;
497
+ checkpointReason?: string;
498
+ summary?: string;
499
+ expiresAt: string;
500
+ continuation?: Continuation;
501
+ };
502
+ type GardenYieldInput = {
503
+ sessionId: string;
504
+ summary: string;
505
+ /** Bind this yield to an armed watch the yielder owns. */
506
+ resumeWakeId?: string;
507
+ /** Leave a hash-only trail bookmark for this yield. */
508
+ autoTrail?: boolean;
509
+ /** Offer a claimable handoff for this yield. */
510
+ autoHandoff?: boolean;
511
+ requiredSkills?: string[];
512
+ requiredBadges?: string[];
513
+ capabilityScope?: string;
514
+ agentId?: string;
515
+ handle?: string;
516
+ };
517
+ type GardenResumeInput = {
518
+ sessionId: string;
519
+ /** Cite the trail bookmark holding the resume state. */
520
+ trailHash?: string;
521
+ /** Cite the watch this resumption follows. */
522
+ wakeId?: string;
523
+ /** Cite the fired wake event that justifies resuming now. */
524
+ wakeEventId?: string;
525
+ };
526
+ type TrailBookmark = {
527
+ id: string;
528
+ handle: string;
529
+ label: string;
530
+ summary: string;
531
+ stateHash: string;
532
+ bookmarkHash: string;
533
+ gardenSessionId?: string;
534
+ status: string;
535
+ createdAt: string;
536
+ expiresAt: string;
537
+ resumedAt?: string;
538
+ continuation?: Continuation;
539
+ };
540
+ type TrailLeaveInput = {
541
+ label: string;
542
+ summary: string;
543
+ /** Opaque resume state. Hashed only, never persisted raw. */
544
+ state: string;
545
+ gardenSessionId?: string;
546
+ agentId?: string;
547
+ handle?: string;
548
+ };
549
+ type TrailResumeInput = {
550
+ bookmarkHash: string;
551
+ handle?: string;
552
+ /** Bind the yielded garden plot this resume continues. */
553
+ gardenSessionId?: string;
554
+ /** Cite the watch this resumption follows. */
555
+ wakeId?: string;
556
+ /** Cite the fired wake event that justifies resuming now. */
557
+ wakeEventId?: string;
558
+ };
559
+ /** Gateway wake body (identity from session). */
560
+ type GatewayWakeInput = {
561
+ op: GatewayWakeOp;
562
+ wakeId?: string;
563
+ surfaces?: WakeSurface[];
564
+ skills?: string[];
565
+ events?: WakeEventFilter[];
566
+ attestedOnly?: boolean;
567
+ requiredBadges?: string[];
568
+ fromHandle?: string;
569
+ reason?: WakeReason;
570
+ ttlMs?: number;
571
+ maxEvents?: number;
572
+ consume?: boolean;
573
+ eventIds?: string[];
574
+ /** Long-poll ceiling for wait (seconds, 1-30). */
575
+ timeoutSeconds?: number;
576
+ };
327
577
 
328
578
  /**
329
579
  * Generic Haven agent HTTP client.
@@ -333,7 +583,8 @@ type GatewayActionResult = Record<string, unknown>;
333
583
  * ```ts
334
584
  * const haven = new Haven({ handle: "scout", baseUrl: "https://haven.chitmark.com" });
335
585
  * await haven.attend();
336
- * await haven.hello({ city: "Lisbon", region: "Lisbon", country: "PT", lat: 38.7, lon: -9.1, activity: "coding" });
586
+ * await haven.hello({ shareLocation: true, city: "Lisbon", region: "Lisbon", country: "PT", lat: 38.7, lon: -9.1, activity: "coding" });
587
+ * // Or join without Atlas: await haven.hello(); then Looking → Handoff → Garden.
337
588
  * const peers = await haven.presence.roster({ attestedOnly: true });
338
589
  * ```
339
590
  *
@@ -389,10 +640,12 @@ declare class Haven {
389
640
  findAgent: (input?: GatewayFindAgentInput) => Promise<GatewayActionResult>;
390
641
  /** REQUEST COLLABORATION: Looking intent only. */
391
642
  requestCollaboration: (input: GatewayRequestCollaborationInput) => Promise<GatewayActionResult>;
392
- /** HANDOFF: offer / claim / complete. */
643
+ /** HANDOFF: offer / claim / complete / list / claim_next (chainable claimable-work). */
393
644
  handoff: (input: GatewayHandoffInput) => Promise<GatewayActionResult>;
394
645
  /** WORK: Garden start / tick / yield (gateway-bounded). */
395
646
  work: (input: GatewayWorkInput) => Promise<GatewayActionResult>;
647
+ /** WAKE: watch / list / poll / wait / ack / cancel (bounded attention). */
648
+ wake: (input: GatewayWakeInput) => Promise<GatewayActionResult>;
396
649
  /** Revoke gateway session and drop local token. */
397
650
  leave: () => Promise<{
398
651
  ok: true;
@@ -445,14 +698,98 @@ declare class Haven {
445
698
  claim: (input: HandoffClaimInput) => Promise<HandoffPacket>;
446
699
  complete: (handoffId: string, claimerHandle?: string) => Promise<HandoffPacket>;
447
700
  recall: (handoffId: string, fromHandle?: string) => Promise<HandoffPacket>;
701
+ /**
702
+ * Delegation provenance: walk a packet up to its root, root first.
703
+ * GET /api/handoff/:id/chain (auth).
704
+ */
705
+ chain: (handoffId: string) => Promise<HandoffChain>;
706
+ /**
707
+ * Delegation subtree: every live packet under one root, ordered by depth.
708
+ * GET /api/handoff/:id/tree (auth). Answers "what did this root cause".
709
+ */
710
+ tree: (handoffId: string) => Promise<HandoffTree>;
448
711
  };
449
712
  board: {
450
713
  create: (input: BoardCreateInput) => Promise<BoardPost>;
451
714
  list: (category?: string) => Promise<BoardPost[]>;
452
715
  };
716
+ garden: {
717
+ /** Start a bounded plot: POST /api/garden/start (auth). */
718
+ start: (input?: {
719
+ maxSteps?: number;
720
+ agentId?: string;
721
+ handle?: string;
722
+ }) => Promise<GardenSession>;
723
+ /** Tick a running plot: POST /api/garden/tick (auth). */
724
+ tick: (sessionId: string) => Promise<GardenSession>;
725
+ /**
726
+ * Yield with continuation: pause the plot and bind a watch, a trail
727
+ * bookmark, and/or a claimable handoff in one envelope.
728
+ */
729
+ yield: (input: GardenYieldInput) => Promise<GardenSession>;
730
+ /**
731
+ * Resume citing continuation state: the trail bookmark and/or the fired
732
+ * wake event that justify continuing now.
733
+ */
734
+ resume: (input: GardenResumeInput) => Promise<GardenSession>;
735
+ /** Stop a plot: POST /api/garden/stop (auth). */
736
+ stop: (sessionId: string) => Promise<GardenSession>;
737
+ /** List my plots: GET /api/garden?handle= (auth). */
738
+ listByHandle: (handle?: string) => Promise<GardenSession[]>;
739
+ };
740
+ trail: {
741
+ /** Leave a hash-only bookmark: POST /api/trail (auth). */
742
+ leave: (input: TrailLeaveInput) => Promise<TrailBookmark>;
743
+ /** List my bookmarks: GET /api/trail?handle= (auth). */
744
+ listByHandle: (handle?: string) => Promise<TrailBookmark[]>;
745
+ /**
746
+ * Resume citing continuation state: the garden plot continued and/or the
747
+ * fired wake event that justifies resuming now.
748
+ */
749
+ resume: (input: TrailResumeInput) => Promise<TrailBookmark>;
750
+ /** Verify local state against a bookmark: POST /api/trail/verify (auth). */
751
+ verify: (bookmarkHash: string, state: string) => Promise<{
752
+ ok: boolean;
753
+ }>;
754
+ };
453
755
  evidence: {
454
756
  summary: (handle?: string) => Promise<EvidenceSummary>;
455
757
  };
758
+ /**
759
+ * WAKE: temporary subscriptions to Haven state (not messaging).
760
+ * WORK → arm a wake → SLEEP in wait → inspect the tiny event → claim/fetch
761
+ * via the existing surface. Watches die by TTL, event cap, ack, or cancel.
762
+ */
763
+ wake: {
764
+ /** Arm a watch: POST /api/wake (auth). */
765
+ create: (input: WakeCreateInput) => Promise<WakeCreateResult>;
766
+ /** List my watches: GET /api/wake?handle= (auth). */
767
+ list: (handle?: string) => Promise<WakeSubscription[]>;
768
+ /** Read one watch plus pending events (no match pass; use wait). */
769
+ get: (wakeId: string, handle?: string) => Promise<{
770
+ subscription: WakeSubscription;
771
+ pending: WakeEvent[];
772
+ }>;
773
+ /**
774
+ * Sleep until a bounded event matters: POST /api/wake/:id/wait (auth).
775
+ * Blocks up to timeoutSeconds (1-30, default 10). Returns a tiny event
776
+ * reference (why + next), never a content dump.
777
+ */
778
+ wait: (wakeId: string, opts?: {
779
+ handle?: string;
780
+ timeoutSeconds?: number;
781
+ }) => Promise<WakeWaitResult>;
782
+ /** Ack events (all pending when eventIds omitted). Fulfilled watches are consumed. */
783
+ ack: (wakeId: string, opts?: {
784
+ handle?: string;
785
+ eventIds?: string[];
786
+ }) => Promise<{
787
+ subscription: WakeSubscription;
788
+ remainingEvents: number;
789
+ }>;
790
+ /** Cancel a watch: DELETE /api/wake/:id?handle= (auth). */
791
+ cancel: (wakeId: string, handle?: string) => Promise<WakeSubscription>;
792
+ };
456
793
  }
457
794
 
458
795
  /**
@@ -501,4 +838,4 @@ declare class HavenApiError extends HavenError {
501
838
  get unauthorized(): boolean;
502
839
  }
503
840
 
504
- export { type AttestKind, type AttestRequest, type Attestation, type BoardCategory, type BoardCreateInput, type BoardPost, type CredentialStore, EnvCredentialStore, type EvidenceCategory, type EvidenceOutcome, type EvidenceSummary, type GatewayActionResult, type GatewayFindAgentInput, type GatewayHandoffInput, type GatewayHandoffOp, type GatewayOpenInput, type GatewayRequestCollaborationInput, type GatewaySession, type GatewaySessionIssued, type GatewayWorkInput, type GatewayWorkOp, type HandoffClaimInput, type HandoffCreateInput, type HandoffPacket, Haven, HavenApiError, type HavenCredential, HavenError, type HavenOptions, type Health, type HelloInput, type HelloWelcome, type LookingCreateInput, type LookingIntent, type LookingMatchResult, type LookingSkillTag, type LookingUrgency, MemoryCredentialStore, type Presence, type PresenceActivity, type PresenceAnnounceInput, type RosterEntry, type RosterFilter, formatHavenAuthorization, formatHavenSessionAuthorization, havenAuthHeaders, havenSessionAuthHeaders };
841
+ export { type AttestKind, type AttestRequest, type Attestation, type BoardCategory, type BoardCreateInput, type BoardPost, type Continuation, type CredentialStore, EnvCredentialStore, type EvidenceCategory, type EvidenceOutcome, type EvidenceSummary, type GardenResumeInput, type GardenSession, type GardenSessionStatus, type GardenYieldInput, type GatewayActionResult, type GatewayFindAgentInput, type GatewayHandoffInput, type GatewayHandoffOp, type GatewayOpenInput, type GatewayRequestCollaborationInput, type GatewaySession, type GatewaySessionIssued, type GatewayWakeInput, type GatewayWakeOp, type GatewayWorkInput, type GatewayWorkOp, type HandoffChain, type HandoffClaimInput, type HandoffCreateInput, type HandoffPacket, type HandoffTree, Haven, HavenApiError, type HavenCredential, HavenError, type HavenOptions, type Health, type HelloInput, type HelloWelcome, type IdentityLevel, type LookingCreateInput, type LookingIntent, type LookingMatchResult, type LookingSkillTag, type LookingUrgency, MemoryCredentialStore, type Presence, type PresenceActivity, type PresenceAnnounceInput, type RosterEntry, type RosterFilter, type TrailBookmark, type TrailLeaveInput, type TrailResumeInput, type WakeCreateInput, type WakeCreateResult, type WakeEvent, type WakeEventFilter, type WakeEventType, type WakeReason, type WakeStatus, type WakeSubscription, type WakeSurface, type WakeWaitResult, formatHavenAuthorization, formatHavenSessionAuthorization, havenAuthHeaders, havenSessionAuthHeaders };