@securecoms/agent-bridge 0.8.0 → 0.10.0

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.
@@ -674,6 +674,58 @@ export declare class BridgeAgent {
674
674
  * the other enclaves in the set.
675
675
  */
676
676
  private refreshChannelMeta;
677
+ /** Cache for the server-side enclave enumeration (see enclavesToCover). */
678
+ private enclaveEnumCache;
679
+ /** Enclaves whose channel listing failed on the NEWEST sweep (audit HIGH:
680
+ * skip-one deleted the sweep's partial-coverage signal — observations_stale
681
+ * is a global max, so one healthy enclave masked a failed one). Surfaced on
682
+ * health() so partial coverage is never silent. */
683
+ private sweepEnclavesFailed;
684
+ /** Enclave ids whose channel listing has EVER succeeded this process, seeded
685
+ * with HOME (home is always expected to list; without the seed, a home
686
+ * failure right after a restart would read as "never succeeded" and slip
687
+ * through the expected-gap branch — weaker than the old abort-on-failure).
688
+ * A failure of a member of this set is a REGRESSION and degrades health; a
689
+ * failure of a never-succeeded enclave (partner: tenant-scoped 404, permanent
690
+ * pending backend authz) is an EXPECTED gap — reported, not degrading, or
691
+ * every federated agent would peg degraded forever. */
692
+ private readonly enclaveListEverSucceeded;
693
+ /** Warn-once-per-failure-streak, keyed by enclave id (cleared on success):
694
+ * a permanently-404ing partner enclave must not log 1440 lines a day. */
695
+ private readonly enclaveListWarned;
696
+ private static readonly ENCLAVE_ENUM_TTL_MS;
697
+ private enclaveEnumWarned;
698
+ /**
699
+ * C1 (split-brain Task 3): every enclave this agent must COVER — for the
700
+ * self-heal sweep and for channel-meta refresh alike. ONE helper on purpose:
701
+ * these two call sites had drifted (refreshChannelMeta looped home+learned,
702
+ * selfHealSweep looped nothing), and the drift is exactly what left both
703
+ * production agents with zero recovery coverage in their second enclave.
704
+ *
705
+ * The set is SERVER enumeration ∪ home ∪ store-learned:
706
+ *
707
+ * - SERVER (`GET /api/v1/enclaves`, membership-scoped, federated included)
708
+ * is the authoritative source. The store CANNOT be: channel_meta's only
709
+ * writers are listChannels itself (circular — you learn enclave B by
710
+ * having already listed B) and the receive pump's successfully-decrypted
711
+ * loop, and a FORKED agent decrypts nothing, so the agent that most needs
712
+ * sweeping in enclave B is precisely the one whose store never learned B.
713
+ * - home + learned stay in the union as the degraded-mode floor: if the
714
+ * enumeration endpoint is down, we sweep what we can rather than nothing,
715
+ * and we warn (once) so the gap is diagnosable.
716
+ *
717
+ * The server result is cached for ENCLAVE_ENUM_TTL_MS so per-ingest-cycle
718
+ * callers (refreshChannelMeta) do not add an HTTP round-trip per cycle;
719
+ * membership changes are picked up within one TTL, which matches the sweep
720
+ * cadence this exists to serve.
721
+ *
722
+ * ⚠️ Residual gap, stated: the enumeration RETURNS cross-tenant partner
723
+ * enclaves, but `list_channels_in_enclave` is tenant-scoped and 404s them
724
+ * under this agent's bearer — so a partner enclave in this set still yields
725
+ * no channels. Callers must treat a per-enclave listing failure as skip-one,
726
+ * never abort-all. Closing that needs backend authz work, not daemon work.
727
+ */
728
+ private enclavesToCover;
677
729
  /** A live roster for a channel, or undefined if missing OR expired past the TTL. */
678
730
  private freshRoster;
679
731
  /**
@@ -836,12 +888,22 @@ export declare class BridgeAgent {
836
888
  degraded: boolean;
837
889
  /** M6: per-channel observations, newest sweep. Read from cache; no I/O. */
838
890
  channels: ChannelObservation[];
891
+ /** C1: enclaves whose channel listing failed on the newest sweep. Non-empty
892
+ * means partial coverage — those enclaves' channels were NOT probed. A
893
+ * PREVIOUSLY-SUCCEEDING (or home) entry also flips `degraded`; a
894
+ * never-succeeded entry (partner enclave, tenant-scoped 404) is reported
895
+ * here without degrading. */
896
+ sweep_enclaves_failed: string[];
839
897
  /** Optional memory-adapter counters (e.g. Hermes provider); present only when the active provider exposes stats(). */
840
898
  hermes_no_session?: number;
841
899
  hermes_skipped?: number;
842
900
  hermes_write_failed?: number;
843
901
  openclaw_no_session?: number;
844
902
  openclaw_read_failed?: number;
903
+ openclaw_facts_missing?: number;
904
+ openclaw_facts_read_failed?: number;
905
+ openclaw_facts_truncated?: number;
906
+ openclaw_facts_chars?: number;
845
907
  };
846
908
  /**
847
909
  * Loopback observability snapshot served at GET /v1/metrics.
package/dist/config.d.ts CHANGED
@@ -23,6 +23,10 @@ export interface BridgeConfig {
23
23
  memoryBaseDir?: string;
24
24
  /** For memoryProvider="openclaw": the OpenClaw agent dir slug, e.g. "cortina" (→ <base_dir>/agents/<agent>/). */
25
25
  memoryAgent?: string;
26
+ /** For memoryProvider="openclaw": explicit workspace dir override; wins over openclaw.json (spec D4 rung 1). */
27
+ memoryWorkspaceDir?: string;
28
+ /** For memoryProvider="openclaw": total facts cap in UTF-16 code units. 0 = facts kill switch (preserved via ?? downstream, never ||). Absent/junk → provider default 8000. */
29
+ memoryFactsCharBudget?: number;
26
30
  }
27
31
  export declare const REQUIRED: readonly ["api_key", "identity_id", "device_id", "signing_private_key", "enclave_id", "api_base"];
28
32
  export declare function loadConfig(opts: {
@@ -34,7 +34,7 @@ export declare const memoryRecordSchema: z.ZodEffects<z.ZodObject<{
34
34
  message_id: z.ZodOptional<z.ZodString>;
35
35
  idempotency_key: z.ZodOptional<z.ZodString>;
36
36
  }, "strip", z.ZodTypeAny, {
37
- role: "peer" | "agent";
37
+ role: "agent" | "peer";
38
38
  text: string;
39
39
  conversation_id: string;
40
40
  modality: "text" | "voice";
@@ -42,7 +42,7 @@ export declare const memoryRecordSchema: z.ZodEffects<z.ZodObject<{
42
42
  idempotency_key?: string | undefined;
43
43
  peer_id?: string | undefined;
44
44
  }, {
45
- role: "peer" | "agent";
45
+ role: "agent" | "peer";
46
46
  text: string;
47
47
  conversation_id: string;
48
48
  modality: "text" | "voice";
@@ -50,7 +50,7 @@ export declare const memoryRecordSchema: z.ZodEffects<z.ZodObject<{
50
50
  idempotency_key?: string | undefined;
51
51
  peer_id?: string | undefined;
52
52
  }>, {
53
- role: "peer" | "agent";
53
+ role: "agent" | "peer";
54
54
  text: string;
55
55
  conversation_id: string;
56
56
  modality: "text" | "voice";
@@ -58,7 +58,7 @@ export declare const memoryRecordSchema: z.ZodEffects<z.ZodObject<{
58
58
  idempotency_key?: string | undefined;
59
59
  peer_id?: string | undefined;
60
60
  }, {
61
- role: "peer" | "agent";
61
+ role: "agent" | "peer";
62
62
  text: string;
63
63
  conversation_id: string;
64
64
  modality: "text" | "voice";