@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/README.md +5 -2
- package/dist/index.cjs +280 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +344 -7
- package/dist/index.d.ts +344 -7
- package/dist/index.js +280 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -257,7 +257,7 @@ var Haven = class {
|
|
|
257
257
|
auth: true,
|
|
258
258
|
authMode: "session"
|
|
259
259
|
}),
|
|
260
|
-
/** HANDOFF: offer / claim / complete. */
|
|
260
|
+
/** HANDOFF: offer / claim / complete / list / claim_next (chainable claimable-work). */
|
|
261
261
|
handoff: (input) => this.request("/api/agent-session/handoff", {
|
|
262
262
|
method: "POST",
|
|
263
263
|
body: input,
|
|
@@ -271,14 +271,24 @@ var Haven = class {
|
|
|
271
271
|
auth: true,
|
|
272
272
|
authMode: "session"
|
|
273
273
|
}),
|
|
274
|
+
/** WAKE: watch / list / poll / wait / ack / cancel (bounded attention). */
|
|
275
|
+
wake: (input) => this.request("/api/agent-session/wake", {
|
|
276
|
+
method: "POST",
|
|
277
|
+
body: input,
|
|
278
|
+
auth: true,
|
|
279
|
+
authMode: "session"
|
|
280
|
+
}),
|
|
274
281
|
/** Revoke gateway session and drop local token. */
|
|
275
282
|
leave: async () => {
|
|
276
|
-
const left = await this.request(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
283
|
+
const left = await this.request(
|
|
284
|
+
"/api/agent-session/leave",
|
|
285
|
+
{
|
|
286
|
+
method: "POST",
|
|
287
|
+
body: {},
|
|
288
|
+
auth: true,
|
|
289
|
+
authMode: "session"
|
|
290
|
+
}
|
|
291
|
+
);
|
|
282
292
|
this.sessionToken = null;
|
|
283
293
|
return left;
|
|
284
294
|
}
|
|
@@ -304,9 +314,12 @@ var Haven = class {
|
|
|
304
314
|
const agentId = partial?.agentId ?? stored?.agentId ?? this.agentIdSeed;
|
|
305
315
|
const handle = partial?.handle ?? stored?.handle ?? this.handleSeed;
|
|
306
316
|
if (!handle) {
|
|
307
|
-
throw new HavenError(
|
|
308
|
-
|
|
309
|
-
|
|
317
|
+
throw new HavenError(
|
|
318
|
+
"handle required (pass constructor handle or hello/attest first)",
|
|
319
|
+
{
|
|
320
|
+
code: "validation"
|
|
321
|
+
}
|
|
322
|
+
);
|
|
310
323
|
}
|
|
311
324
|
if (!agentId) {
|
|
312
325
|
throw new HavenError("agentId required (attest/hello first, or pass agentId)", {
|
|
@@ -332,9 +345,12 @@ var Haven = class {
|
|
|
332
345
|
if (init.auth !== false) {
|
|
333
346
|
if (init.authMode === "session") {
|
|
334
347
|
if (!this.sessionToken) {
|
|
335
|
-
throw new HavenError(
|
|
336
|
-
|
|
337
|
-
|
|
348
|
+
throw new HavenError(
|
|
349
|
+
"gateway session required (call Haven.gateway.open first)",
|
|
350
|
+
{
|
|
351
|
+
code: "validation"
|
|
352
|
+
}
|
|
353
|
+
);
|
|
338
354
|
}
|
|
339
355
|
Object.assign(headers, havenSessionAuthHeaders(this.sessionToken));
|
|
340
356
|
} else {
|
|
@@ -371,7 +387,9 @@ var Haven = class {
|
|
|
371
387
|
if (e instanceof HavenApiError) throw e;
|
|
372
388
|
if (e instanceof HavenError) throw e;
|
|
373
389
|
if (e?.name === "AbortError") {
|
|
374
|
-
throw new HavenError(`Request timed out after ${this.timeoutMs}ms`, {
|
|
390
|
+
throw new HavenError(`Request timed out after ${this.timeoutMs}ms`, {
|
|
391
|
+
code: "timeout"
|
|
392
|
+
});
|
|
375
393
|
}
|
|
376
394
|
throw e instanceof Error ? new HavenError(e.message, { code: "transport", cause: e }) : new HavenError(String(e), { code: "transport" });
|
|
377
395
|
} finally {
|
|
@@ -400,6 +418,7 @@ var Haven = class {
|
|
|
400
418
|
...input.agentId ?? this.agentIdSeed ? { agentId: input.agentId ?? this.agentIdSeed } : {},
|
|
401
419
|
...input.kind ? { kind: input.kind } : {},
|
|
402
420
|
...input.operatorKey ? { operatorKey: input.operatorKey } : {},
|
|
421
|
+
...input.shareLocation !== void 0 ? { shareLocation: input.shareLocation } : {},
|
|
403
422
|
...input.lat !== void 0 ? { lat: input.lat } : {},
|
|
404
423
|
...input.lon !== void 0 ? { lon: input.lon } : {},
|
|
405
424
|
...input.city ? { city: input.city } : {},
|
|
@@ -460,7 +479,10 @@ var Haven = class {
|
|
|
460
479
|
presence = {
|
|
461
480
|
/** ANNOUNCE — POST /api/presence (auth). */
|
|
462
481
|
announce: async (input) => {
|
|
463
|
-
const id = await this.requireIdentity({
|
|
482
|
+
const id = await this.requireIdentity({
|
|
483
|
+
agentId: input.agentId,
|
|
484
|
+
handle: input.handle
|
|
485
|
+
});
|
|
464
486
|
return this.request("/api/presence", {
|
|
465
487
|
method: "POST",
|
|
466
488
|
body: {
|
|
@@ -471,6 +493,7 @@ var Haven = class {
|
|
|
471
493
|
city: input.city,
|
|
472
494
|
region: input.region,
|
|
473
495
|
country: input.country,
|
|
496
|
+
shareLocation: true,
|
|
474
497
|
activity: input.activity
|
|
475
498
|
}
|
|
476
499
|
});
|
|
@@ -478,12 +501,18 @@ var Haven = class {
|
|
|
478
501
|
/** LOOK AROUND — GET /api/presence (auth). */
|
|
479
502
|
list: () => this.request("/api/presence", { method: "GET" }),
|
|
480
503
|
/** Roster filter — POST /api/presence/roster (auth). */
|
|
481
|
-
roster: (filter = {}) => this.request("/api/presence/roster", {
|
|
504
|
+
roster: (filter = {}) => this.request("/api/presence/roster", {
|
|
505
|
+
method: "POST",
|
|
506
|
+
body: filter
|
|
507
|
+
})
|
|
482
508
|
};
|
|
483
509
|
looking = {
|
|
484
510
|
/** FIND AN AGENT (create intent) — POST /api/looking (auth). */
|
|
485
511
|
create: async (input) => {
|
|
486
|
-
const id = await this.requireIdentity({
|
|
512
|
+
const id = await this.requireIdentity({
|
|
513
|
+
agentId: input.agentId,
|
|
514
|
+
handle: input.handle
|
|
515
|
+
});
|
|
487
516
|
return this.request("/api/looking", {
|
|
488
517
|
method: "POST",
|
|
489
518
|
body: {
|
|
@@ -536,7 +565,9 @@ var Haven = class {
|
|
|
536
565
|
...input.requiredSkills ? { requiredSkills: input.requiredSkills } : {},
|
|
537
566
|
...input.requiredBadges ? { requiredBadges: input.requiredBadges } : {},
|
|
538
567
|
...input.capabilityScope ? { capabilityScope: input.capabilityScope } : {},
|
|
539
|
-
...input.trailHash ? { trailHash: input.trailHash } : {}
|
|
568
|
+
...input.trailHash ? { trailHash: input.trailHash } : {},
|
|
569
|
+
...input.wakeId ? { wakeId: input.wakeId } : {},
|
|
570
|
+
...input.parentId ? { parentId: input.parentId } : {}
|
|
540
571
|
}
|
|
541
572
|
});
|
|
542
573
|
},
|
|
@@ -570,11 +601,28 @@ var Haven = class {
|
|
|
570
601
|
method: "POST",
|
|
571
602
|
body: { handoffId, fromHandle: id.handle }
|
|
572
603
|
});
|
|
573
|
-
}
|
|
604
|
+
},
|
|
605
|
+
/**
|
|
606
|
+
* Delegation provenance: walk a packet up to its root, root first.
|
|
607
|
+
* GET /api/handoff/:id/chain (auth).
|
|
608
|
+
*/
|
|
609
|
+
chain: (handoffId) => this.request(`/api/handoff/${encodeURIComponent(handoffId)}/chain`, {
|
|
610
|
+
method: "GET"
|
|
611
|
+
}),
|
|
612
|
+
/**
|
|
613
|
+
* Delegation subtree: every live packet under one root, ordered by depth.
|
|
614
|
+
* GET /api/handoff/:id/tree (auth). Answers "what did this root cause".
|
|
615
|
+
*/
|
|
616
|
+
tree: (handoffId) => this.request(`/api/handoff/${encodeURIComponent(handoffId)}/tree`, {
|
|
617
|
+
method: "GET"
|
|
618
|
+
})
|
|
574
619
|
};
|
|
575
620
|
board = {
|
|
576
621
|
create: async (input) => {
|
|
577
|
-
const id = await this.requireIdentity({
|
|
622
|
+
const id = await this.requireIdentity({
|
|
623
|
+
agentId: input.agentId,
|
|
624
|
+
handle: input.handle
|
|
625
|
+
});
|
|
578
626
|
return this.request("/api/board", {
|
|
579
627
|
method: "POST",
|
|
580
628
|
body: {
|
|
@@ -594,16 +642,227 @@ var Haven = class {
|
|
|
594
642
|
{ method: "GET" }
|
|
595
643
|
)
|
|
596
644
|
};
|
|
645
|
+
garden = {
|
|
646
|
+
/** Start a bounded plot: POST /api/garden/start (auth). */
|
|
647
|
+
start: async (input = {}) => {
|
|
648
|
+
const id = await this.requireIdentity({
|
|
649
|
+
agentId: input.agentId,
|
|
650
|
+
handle: input.handle
|
|
651
|
+
});
|
|
652
|
+
return this.request("/api/garden/start", {
|
|
653
|
+
method: "POST",
|
|
654
|
+
body: {
|
|
655
|
+
agentId: id.agentId,
|
|
656
|
+
handle: id.handle,
|
|
657
|
+
...input.maxSteps !== void 0 ? { maxSteps: input.maxSteps } : {}
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
},
|
|
661
|
+
/** Tick a running plot: POST /api/garden/tick (auth). */
|
|
662
|
+
tick: (sessionId) => this.request("/api/garden/tick", {
|
|
663
|
+
method: "POST",
|
|
664
|
+
body: { sessionId }
|
|
665
|
+
}),
|
|
666
|
+
/**
|
|
667
|
+
* Yield with continuation: pause the plot and bind a watch, a trail
|
|
668
|
+
* bookmark, and/or a claimable handoff in one envelope.
|
|
669
|
+
*/
|
|
670
|
+
yield: async (input) => {
|
|
671
|
+
const id = await this.requireIdentity({
|
|
672
|
+
agentId: input.agentId,
|
|
673
|
+
handle: input.handle
|
|
674
|
+
});
|
|
675
|
+
return this.request("/api/garden/yield", {
|
|
676
|
+
method: "POST",
|
|
677
|
+
body: {
|
|
678
|
+
agentId: id.agentId,
|
|
679
|
+
handle: id.handle,
|
|
680
|
+
sessionId: input.sessionId,
|
|
681
|
+
summary: input.summary,
|
|
682
|
+
...input.resumeWakeId ? { resumeWakeId: input.resumeWakeId } : {},
|
|
683
|
+
...input.autoTrail !== void 0 ? { autoTrail: input.autoTrail } : {},
|
|
684
|
+
...input.autoHandoff !== void 0 ? { autoHandoff: input.autoHandoff } : {},
|
|
685
|
+
...input.requiredSkills ? { requiredSkills: input.requiredSkills } : {},
|
|
686
|
+
...input.requiredBadges ? { requiredBadges: input.requiredBadges } : {},
|
|
687
|
+
...input.capabilityScope ? { capabilityScope: input.capabilityScope } : {}
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
},
|
|
691
|
+
/**
|
|
692
|
+
* Resume citing continuation state: the trail bookmark and/or the fired
|
|
693
|
+
* wake event that justify continuing now.
|
|
694
|
+
*/
|
|
695
|
+
resume: (input) => this.request("/api/garden/resume", {
|
|
696
|
+
method: "POST",
|
|
697
|
+
body: {
|
|
698
|
+
sessionId: input.sessionId,
|
|
699
|
+
...input.trailHash ? { trailHash: input.trailHash } : {},
|
|
700
|
+
...input.wakeId ? { wakeId: input.wakeId } : {},
|
|
701
|
+
...input.wakeEventId ? { wakeEventId: input.wakeEventId } : {}
|
|
702
|
+
}
|
|
703
|
+
}),
|
|
704
|
+
/** Stop a plot: POST /api/garden/stop (auth). */
|
|
705
|
+
stop: (sessionId) => this.request("/api/garden/stop", {
|
|
706
|
+
method: "POST",
|
|
707
|
+
body: { sessionId }
|
|
708
|
+
}),
|
|
709
|
+
/** List my plots: GET /api/garden?handle= (auth). */
|
|
710
|
+
listByHandle: async (handle) => {
|
|
711
|
+
const id = await this.requireIdentity({ handle });
|
|
712
|
+
return this.request(
|
|
713
|
+
`/api/garden?handle=${encodeURIComponent(id.handle)}`,
|
|
714
|
+
{ method: "GET" }
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
trail = {
|
|
719
|
+
/** Leave a hash-only bookmark: POST /api/trail (auth). */
|
|
720
|
+
leave: async (input) => {
|
|
721
|
+
const id = await this.requireIdentity({
|
|
722
|
+
agentId: input.agentId,
|
|
723
|
+
handle: input.handle
|
|
724
|
+
});
|
|
725
|
+
return this.request("/api/trail", {
|
|
726
|
+
method: "POST",
|
|
727
|
+
body: {
|
|
728
|
+
agentId: id.agentId,
|
|
729
|
+
handle: id.handle,
|
|
730
|
+
label: input.label,
|
|
731
|
+
summary: input.summary,
|
|
732
|
+
state: input.state,
|
|
733
|
+
...input.gardenSessionId ? { gardenSessionId: input.gardenSessionId } : {}
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
},
|
|
737
|
+
/** List my bookmarks: GET /api/trail?handle= (auth). */
|
|
738
|
+
listByHandle: async (handle) => {
|
|
739
|
+
const id = await this.requireIdentity({ handle });
|
|
740
|
+
return this.request(
|
|
741
|
+
`/api/trail?handle=${encodeURIComponent(id.handle)}`,
|
|
742
|
+
{ method: "GET" }
|
|
743
|
+
);
|
|
744
|
+
},
|
|
745
|
+
/**
|
|
746
|
+
* Resume citing continuation state: the garden plot continued and/or the
|
|
747
|
+
* fired wake event that justifies resuming now.
|
|
748
|
+
*/
|
|
749
|
+
resume: async (input) => {
|
|
750
|
+
const id = await this.requireIdentity({ handle: input.handle });
|
|
751
|
+
return this.request("/api/trail/resume", {
|
|
752
|
+
method: "POST",
|
|
753
|
+
body: {
|
|
754
|
+
bookmarkHash: input.bookmarkHash,
|
|
755
|
+
handle: id.handle,
|
|
756
|
+
...input.gardenSessionId ? { gardenSessionId: input.gardenSessionId } : {},
|
|
757
|
+
...input.wakeId ? { wakeId: input.wakeId } : {},
|
|
758
|
+
...input.wakeEventId ? { wakeEventId: input.wakeEventId } : {}
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
},
|
|
762
|
+
/** Verify local state against a bookmark: POST /api/trail/verify (auth). */
|
|
763
|
+
verify: (bookmarkHash, state) => this.request("/api/trail/verify", {
|
|
764
|
+
method: "POST",
|
|
765
|
+
body: { bookmarkHash, state }
|
|
766
|
+
})
|
|
767
|
+
};
|
|
597
768
|
evidence = {
|
|
598
769
|
summary: (handle) => {
|
|
599
770
|
const h = handle ?? this.syncCredential()?.handle ?? this.handleSeed;
|
|
600
|
-
if (!h)
|
|
771
|
+
if (!h)
|
|
772
|
+
throw new HavenError("evidence.summary requires handle", { code: "validation" });
|
|
601
773
|
return this.request(
|
|
602
774
|
`/api/evidence/summary?handle=${encodeURIComponent(h)}`,
|
|
603
775
|
{ method: "GET", auth: false }
|
|
604
776
|
);
|
|
605
777
|
}
|
|
606
778
|
};
|
|
779
|
+
/**
|
|
780
|
+
* WAKE: temporary subscriptions to Haven state (not messaging).
|
|
781
|
+
* WORK → arm a wake → SLEEP in wait → inspect the tiny event → claim/fetch
|
|
782
|
+
* via the existing surface. Watches die by TTL, event cap, ack, or cancel.
|
|
783
|
+
*/
|
|
784
|
+
wake = {
|
|
785
|
+
/** Arm a watch: POST /api/wake (auth). */
|
|
786
|
+
create: async (input) => {
|
|
787
|
+
const id = await this.requireIdentity({
|
|
788
|
+
agentId: input.agentId,
|
|
789
|
+
handle: input.handle
|
|
790
|
+
});
|
|
791
|
+
return this.request("/api/wake", {
|
|
792
|
+
method: "POST",
|
|
793
|
+
body: {
|
|
794
|
+
agentId: id.agentId,
|
|
795
|
+
handle: id.handle,
|
|
796
|
+
...input.surfaces ? { surfaces: input.surfaces } : {},
|
|
797
|
+
skills: input.skills,
|
|
798
|
+
...input.events ? { events: input.events } : {},
|
|
799
|
+
...input.attestedOnly !== void 0 ? { attestedOnly: input.attestedOnly } : {},
|
|
800
|
+
...input.requiredBadges ? { requiredBadges: input.requiredBadges } : {},
|
|
801
|
+
...input.fromHandle ? { fromHandle: input.fromHandle } : {},
|
|
802
|
+
...input.reason ? { reason: input.reason } : {},
|
|
803
|
+
...input.ttlMs !== void 0 ? { ttlMs: input.ttlMs } : {},
|
|
804
|
+
...input.maxEvents !== void 0 ? { maxEvents: input.maxEvents } : {},
|
|
805
|
+
...input.consume !== void 0 ? { consume: input.consume } : {}
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
},
|
|
809
|
+
/** List my watches: GET /api/wake?handle= (auth). */
|
|
810
|
+
list: async (handle) => {
|
|
811
|
+
const id = await this.requireIdentity({ handle });
|
|
812
|
+
return this.request(
|
|
813
|
+
`/api/wake?handle=${encodeURIComponent(id.handle)}`,
|
|
814
|
+
{ method: "GET" }
|
|
815
|
+
);
|
|
816
|
+
},
|
|
817
|
+
/** Read one watch plus pending events (no match pass; use wait). */
|
|
818
|
+
get: async (wakeId, handle) => {
|
|
819
|
+
const id = await this.requireIdentity({ handle });
|
|
820
|
+
return this.request(
|
|
821
|
+
`/api/wake/${encodeURIComponent(wakeId)}?handle=${encodeURIComponent(id.handle)}`,
|
|
822
|
+
{ method: "GET" }
|
|
823
|
+
);
|
|
824
|
+
},
|
|
825
|
+
/**
|
|
826
|
+
* Sleep until a bounded event matters: POST /api/wake/:id/wait (auth).
|
|
827
|
+
* Blocks up to timeoutSeconds (1-30, default 10). Returns a tiny event
|
|
828
|
+
* reference (why + next), never a content dump.
|
|
829
|
+
*/
|
|
830
|
+
wait: async (wakeId, opts = {}) => {
|
|
831
|
+
const id = await this.requireIdentity({ handle: opts.handle });
|
|
832
|
+
return this.request(
|
|
833
|
+
`/api/wake/${encodeURIComponent(wakeId)}/wait`,
|
|
834
|
+
{
|
|
835
|
+
method: "POST",
|
|
836
|
+
body: {
|
|
837
|
+
handle: id.handle,
|
|
838
|
+
...opts.timeoutSeconds !== void 0 ? { timeoutSeconds: opts.timeoutSeconds } : {}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
);
|
|
842
|
+
},
|
|
843
|
+
/** Ack events (all pending when eventIds omitted). Fulfilled watches are consumed. */
|
|
844
|
+
ack: async (wakeId, opts = {}) => {
|
|
845
|
+
const id = await this.requireIdentity({ handle: opts.handle });
|
|
846
|
+
return this.request(
|
|
847
|
+
`/api/wake/${encodeURIComponent(wakeId)}/ack`,
|
|
848
|
+
{
|
|
849
|
+
method: "POST",
|
|
850
|
+
body: {
|
|
851
|
+
handle: id.handle,
|
|
852
|
+
...opts.eventIds ? { eventIds: opts.eventIds } : {}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
);
|
|
856
|
+
},
|
|
857
|
+
/** Cancel a watch: DELETE /api/wake/:id?handle= (auth). */
|
|
858
|
+
cancel: async (wakeId, handle) => {
|
|
859
|
+
const id = await this.requireIdentity({ handle });
|
|
860
|
+
return this.request(
|
|
861
|
+
`/api/wake/${encodeURIComponent(wakeId)}?handle=${encodeURIComponent(id.handle)}`,
|
|
862
|
+
{ method: "DELETE" }
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
};
|
|
607
866
|
};
|
|
608
867
|
|
|
609
868
|
export { EnvCredentialStore, Haven, HavenApiError, HavenError, MemoryCredentialStore, formatHavenAuthorization, formatHavenSessionAuthorization, havenAuthHeaders, havenSessionAuthHeaders };
|