network-ai 3.7.0 → 3.8.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.
@@ -0,0 +1,274 @@
1
+ "use strict";
2
+ /**
3
+ * Configurable Consistency Levels for Blackboard Backends
4
+ *
5
+ * Wraps any `BlackboardBackend` with one of three consistency guarantees:
6
+ *
7
+ * - `'eventual'` (default) — writes return immediately; async replication
8
+ * happens in the background. Highest throughput.
9
+ * - `'session'` — read-your-writes guarantee. Every write made
10
+ * by this instance is immediately visible to
11
+ * subsequent reads, even before it propagates to
12
+ * other nodes. Tracked in a local session cache.
13
+ * - `'strong'` — writes are flushed to the backend before the
14
+ * async `writeAsync()` resolves. For backends
15
+ * that implement `FlushableBackend` (e.g.
16
+ * `RedisBackend`, `CrdtBackend`) this guarantees
17
+ * durability before the caller continues.
18
+ *
19
+ * Usage:
20
+ * ```typescript
21
+ * import { MemoryBackend } from './blackboard-backend';
22
+ * import { ConsistentBackend } from './consistency';
23
+ *
24
+ * const backend = new ConsistentBackend(new MemoryBackend(), 'session');
25
+ * backend.write('k', 'v', 'agent-1');
26
+ * backend.read('k'); // always returns 'v' in this session
27
+ * ```
28
+ *
29
+ * Integration with `getBlackboard()`:
30
+ * ```typescript
31
+ * const board = orchestrator.getBlackboard('live', {
32
+ * backend: new RedisBackend(client),
33
+ * consistency: 'strong',
34
+ * });
35
+ * ```
36
+ *
37
+ * @module Consistency
38
+ * @version 1.0.0
39
+ * @license MIT
40
+ */
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.ConsistentBackend = void 0;
43
+ exports.isFlushable = isFlushable;
44
+ /**
45
+ * Type guard — returns `true` if `backend` implements `FlushableBackend`.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * if (isFlushable(backend)) {
50
+ * await backend.flush();
51
+ * }
52
+ * ```
53
+ */
54
+ function isFlushable(backend) {
55
+ return typeof backend.flush === 'function';
56
+ }
57
+ // ============================================================================
58
+ // CONSISTENT BACKEND
59
+ // ============================================================================
60
+ /**
61
+ * A `BlackboardBackend` wrapper that adds configurable consistency semantics.
62
+ *
63
+ * Fully satisfies the synchronous `BlackboardBackend` interface so it can be
64
+ * used anywhere a plain backend is accepted. For `'strong'` consistency, use
65
+ * `writeAsync()` to await durability confirmation.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * // Session consistency — read-your-writes
70
+ * const backend = new ConsistentBackend(new MemoryBackend(), 'session');
71
+ * backend.write('task', 'pending', 'agent-1');
72
+ * backend.read('task'); // → 'pending' (guaranteed, even before replication)
73
+ *
74
+ * // Strong consistency with Redis
75
+ * const backend = new ConsistentBackend(new RedisBackend(client), 'strong');
76
+ * await backend.writeAsync('result', data, 'agent-1');
77
+ * // Redis has confirmed the write
78
+ * ```
79
+ */
80
+ class ConsistentBackend {
81
+ _backend;
82
+ _level;
83
+ /**
84
+ * Session write cache.
85
+ *
86
+ * - `BlackboardEntry` → written in this session (overrides backend reads)
87
+ * - `null` → deleted in this session (hides backend reads)
88
+ *
89
+ * Only populated for `'session'` consistency.
90
+ */
91
+ _session = new Map();
92
+ /**
93
+ * Create a new `ConsistentBackend`.
94
+ *
95
+ * @param backend The underlying storage backend to wrap.
96
+ * @param level Consistency level. Defaults to `'eventual'`.
97
+ */
98
+ constructor(backend, level = 'eventual') {
99
+ this._backend = backend;
100
+ this._level = level;
101
+ }
102
+ // --------------------------------------------------------------------------
103
+ // BlackboardBackend interface
104
+ // --------------------------------------------------------------------------
105
+ /**
106
+ * Read an entry.
107
+ *
108
+ * - `eventual` / `strong`: delegates directly to the underlying backend.
109
+ * - `session`: returns the session-cached entry if present; falls back to
110
+ * the backend. Returns `null` for session-deleted keys even if the backend
111
+ * still has them.
112
+ */
113
+ read(key) {
114
+ if (this._level === 'session') {
115
+ const cached = this._session.get(key);
116
+ if (cached === undefined) {
117
+ // Not in session cache — fall through to backend
118
+ }
119
+ else if (cached === null) {
120
+ // Session-deleted tombstone
121
+ return null;
122
+ }
123
+ else {
124
+ // Live session entry — check expiry
125
+ if (this._isExpired(cached)) {
126
+ this._session.delete(key);
127
+ return null;
128
+ }
129
+ return cached;
130
+ }
131
+ }
132
+ return this._backend.read(key);
133
+ }
134
+ /**
135
+ * Write a value synchronously.
136
+ *
137
+ * For all consistency levels this writes immediately to the underlying
138
+ * backend. For `'session'` the result is also cached locally so subsequent
139
+ * `read()` calls see it without waiting for replication.
140
+ *
141
+ * For `'strong'` consistency, prefer `writeAsync()` to await durability.
142
+ */
143
+ write(key, value, sourceAgent, ttl) {
144
+ const entry = this._backend.write(key, value, sourceAgent, ttl);
145
+ if (this._level === 'session') {
146
+ this._session.set(key, entry);
147
+ }
148
+ return entry;
149
+ }
150
+ /**
151
+ * Delete an entry.
152
+ *
153
+ * For `'session'` consistency, also records a session-tombstone so the key
154
+ * appears deleted to subsequent `read()` calls in this session.
155
+ */
156
+ delete(key) {
157
+ const result = this._backend.delete(key);
158
+ if (this._level === 'session') {
159
+ this._session.set(key, null); // tombstone
160
+ }
161
+ return result;
162
+ }
163
+ /**
164
+ * Return all non-expired, non-deleted keys.
165
+ *
166
+ * For `'session'` consistency, session-written keys are included even if
167
+ * not yet visible in the backend; session-deleted keys are excluded.
168
+ */
169
+ listKeys() {
170
+ if (this._level !== 'session') {
171
+ return this._backend.listKeys();
172
+ }
173
+ // Start with backend keys, then overlay session mutations
174
+ const backendKeys = new Set(this._backend.listKeys());
175
+ // Add session-written keys (not yet in backend, or overriding backend)
176
+ for (const [key, entry] of this._session.entries()) {
177
+ if (entry === null) {
178
+ // Session delete — remove from result
179
+ backendKeys.delete(key);
180
+ }
181
+ else if (!this._isExpired(entry)) {
182
+ backendKeys.add(key);
183
+ }
184
+ }
185
+ return Array.from(backendKeys);
186
+ }
187
+ /**
188
+ * Return a snapshot of all non-expired, non-deleted entries.
189
+ *
190
+ * For `'session'` consistency, session writes overlay the backend snapshot.
191
+ */
192
+ getSnapshot() {
193
+ if (this._level !== 'session') {
194
+ return this._backend.getSnapshot();
195
+ }
196
+ // Start from backend snapshot, apply session overlay
197
+ const result = { ...this._backend.getSnapshot() };
198
+ for (const [key, entry] of this._session.entries()) {
199
+ if (entry === null) {
200
+ // Session delete
201
+ delete result[key];
202
+ }
203
+ else if (!this._isExpired(entry)) {
204
+ result[key] = entry;
205
+ }
206
+ }
207
+ return result;
208
+ }
209
+ // --------------------------------------------------------------------------
210
+ // Extended consistency API
211
+ // --------------------------------------------------------------------------
212
+ /**
213
+ * Write a value and, for `'strong'` consistency, await durability
214
+ * confirmation from the backend.
215
+ *
216
+ * - `eventual` / `session`: behaves identically to `write()` but returns
217
+ * a `Promise` for API uniformity.
218
+ * - `strong` + `FlushableBackend`: calls `backend.flush()` after the write
219
+ * and resolves only after the flush completes.
220
+ * - `strong` + non-flushable backend: writes synchronously and resolves
221
+ * immediately (backend writes are already synchronous/durable).
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * const entry = await backend.writeAsync('checkpoint', data, 'agent-1');
226
+ * // Under 'strong' + RedisBackend: Redis has persisted the entry by here
227
+ * ```
228
+ */
229
+ async writeAsync(key, value, sourceAgent, ttl) {
230
+ const entry = this.write(key, value, sourceAgent, ttl);
231
+ if (this._level === 'strong' && isFlushable(this._backend)) {
232
+ await this._backend.flush();
233
+ }
234
+ return entry;
235
+ }
236
+ /**
237
+ * The configured consistency level.
238
+ */
239
+ get consistencyLevel() {
240
+ return this._level;
241
+ }
242
+ /**
243
+ * The underlying backend being wrapped.
244
+ */
245
+ get backend() {
246
+ return this._backend;
247
+ }
248
+ /**
249
+ * Number of entries currently in the session cache (live + tombstones).
250
+ * Always `0` for `'eventual'` and `'strong'` levels.
251
+ */
252
+ get sessionSize() {
253
+ return this._session.size;
254
+ }
255
+ /**
256
+ * Clear the session write cache without modifying the underlying backend.
257
+ *
258
+ * After calling this, `read()` will reflect the backend state directly.
259
+ * Only meaningful for `'session'` consistency.
260
+ */
261
+ clearSession() {
262
+ this._session.clear();
263
+ }
264
+ // --------------------------------------------------------------------------
265
+ // Private helpers
266
+ // --------------------------------------------------------------------------
267
+ _isExpired(entry) {
268
+ if (!entry.ttl)
269
+ return false;
270
+ return Date.now() > new Date(entry.timestamp).getTime() + entry.ttl * 1000;
271
+ }
272
+ }
273
+ exports.ConsistentBackend = ConsistentBackend;
274
+ //# sourceMappingURL=consistency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consistency.js","sourceRoot":"","sources":["../../lib/consistency.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Federated Budget Tracking
3
+ *
4
+ * Tracks token spending across distributed agent swarms. Each `FederatedBudget`
5
+ * instance enforces a global ceiling shared among all agents that call `spend()`.
6
+ *
7
+ * When an optional `BlackboardBackend` is supplied, the budget state is written
8
+ * to the blackboard after every mutation. Wiring a `CrdtBackend` or `RedisBackend`
9
+ * as the underlying backend therefore gives automatic cross-node synchronization
10
+ * with no extra configuration.
11
+ *
12
+ * Architecture:
13
+ * - In-memory `spent` map keyed by `agentId` holds per-agent cumulative totals.
14
+ * - `spend()` is synchronous and enforces both the global ceiling and an optional
15
+ * per-agent ceiling in a single check.
16
+ * - A `blackboard` backend (if supplied) stores a JSON snapshot under `budgetKey`
17
+ * after every `spend()` / `reset()` / `setCeiling()` call so distributed nodes
18
+ * can read the latest state.
19
+ * - `loadFromBlackboard()` deserializes a previously saved snapshot so a
20
+ * restarted node can recover its prior accumulated spend.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * import { FederatedBudget } from 'network-ai';
25
+ *
26
+ * const budget = new FederatedBudget({ ceiling: 10_000 });
27
+ *
28
+ * budget.spend('agent-1', 3000); // { allowed: true, remaining: 7000 }
29
+ * budget.spend('agent-2', 8000); // { allowed: false, remaining: 7000 }
30
+ * budget.remaining(); // 7000
31
+ * budget.getSpendLog(); // { 'agent-1': 3000 }
32
+ * ```
33
+ *
34
+ * @example With blackboard persistence
35
+ * ```typescript
36
+ * import { CrdtBackend } from 'network-ai';
37
+ * import { FederatedBudget } from 'network-ai';
38
+ *
39
+ * const node = new CrdtBackend('node-a');
40
+ * const budget = new FederatedBudget({ ceiling: 50_000, blackboard: node });
41
+ *
42
+ * budget.spend('agent-1', 1000);
43
+ * // State is now stored in node under 'federated-budget'
44
+ * // Sync node to other CrdtBackend nodes to propagate the spend.
45
+ * ```
46
+ *
47
+ * @module FederatedBudget
48
+ * @version 1.0.0
49
+ * @license MIT
50
+ */
51
+ import type { BlackboardBackend } from './blackboard-backend';
52
+ /**
53
+ * Result returned by {@link FederatedBudget.spend}.
54
+ */
55
+ export interface SpendResult {
56
+ /** Whether the spend was allowed (i.e. did not breach any ceiling). */
57
+ allowed: boolean;
58
+ /** Remaining tokens in the global pool after this call. */
59
+ remaining: number;
60
+ /** Reason the spend was denied, if `allowed` is `false`. */
61
+ deniedReason?: 'global_ceiling' | 'per_agent_ceiling';
62
+ }
63
+ /**
64
+ * A single entry in the spend log returned by {@link FederatedBudget.getSpendLog}.
65
+ */
66
+ export interface SpendLogEntry {
67
+ /** Agent that made the spend. */
68
+ agentId: string;
69
+ /** Number of tokens spent in this transaction. */
70
+ tokens: number;
71
+ /** ISO timestamp of the spend. */
72
+ timestamp: string;
73
+ }
74
+ /**
75
+ * Construction options for {@link FederatedBudget}.
76
+ */
77
+ export interface FederatedBudgetOptions {
78
+ /**
79
+ * Global token ceiling shared across all agents.
80
+ * No single call to `spend()` may push the cumulative total above this value.
81
+ * Must be a positive integer.
82
+ */
83
+ ceiling: number;
84
+ /**
85
+ * Optional per-agent ceiling.
86
+ * When set, each individual agent is also capped at this many cumulative tokens,
87
+ * independently of the global ceiling.
88
+ * Must be a positive integer if provided.
89
+ */
90
+ perAgentCeiling?: number;
91
+ /**
92
+ * Optional blackboard backend.
93
+ * When provided, budget state is persisted under `budgetKey` after every
94
+ * mutation so distributed nodes can observe the latest spend.
95
+ *
96
+ * Pair with a `CrdtBackend` or `RedisBackend` for automatic multi-node sync.
97
+ */
98
+ blackboard?: BlackboardBackend;
99
+ /**
100
+ * Key used to store the budget snapshot on the blackboard.
101
+ * Defaults to `'federated-budget'`.
102
+ */
103
+ budgetKey?: string;
104
+ /**
105
+ * Agent identifier used as the `agentId` when writing to the blackboard.
106
+ * Defaults to `'federated-budget-tracker'`.
107
+ */
108
+ blackboardAgent?: string;
109
+ }
110
+ /**
111
+ * Federated token-budget tracker for distributed agent swarms.
112
+ *
113
+ * Enforces a shared global ceiling across all agents and optionally an
114
+ * individual per-agent ceiling. State can be persisted to any
115
+ * `BlackboardBackend` for cross-node visibility.
116
+ */
117
+ export declare class FederatedBudget {
118
+ private readonly _ceiling;
119
+ private _dynamicCeiling;
120
+ private readonly _perAgentCeiling;
121
+ private readonly _spent;
122
+ private _totalSpent;
123
+ private readonly _log;
124
+ private readonly _blackboard;
125
+ private readonly _budgetKey;
126
+ private readonly _bbAgent;
127
+ constructor(options: FederatedBudgetOptions);
128
+ /**
129
+ * Attempt to spend `tokens` on behalf of `agentId`.
130
+ *
131
+ * The spend is allowed only when:
132
+ * 1. `totalSpent + tokens <= ceiling` (global ceiling not breached), AND
133
+ * 2. `agentSpent + tokens <= perAgentCeiling` if a per-agent ceiling is set.
134
+ *
135
+ * When allowed the internal counters are updated and the state is persisted
136
+ * to the blackboard (if configured).
137
+ *
138
+ * @param agentId Identifier of the spending agent. Must be a non-empty string.
139
+ * @param tokens Number of tokens to spend. Must be a positive integer.
140
+ * @returns `SpendResult` with `allowed`, `remaining`, and optional `deniedReason`.
141
+ */
142
+ spend(agentId: string, tokens: number): SpendResult;
143
+ /**
144
+ * Remaining tokens in the global pool.
145
+ */
146
+ remaining(): number;
147
+ /**
148
+ * Total tokens spent across all agents.
149
+ */
150
+ getTotalSpent(): number;
151
+ /**
152
+ * Tokens spent by a specific agent. Returns `0` if the agent has no spend.
153
+ */
154
+ getAgentSpent(agentId: string): number;
155
+ /**
156
+ * Per-agent spend totals as a plain object: `{ agentId: totalTokens }`.
157
+ */
158
+ getSpendLog(): Record<string, number>;
159
+ /**
160
+ * Detailed transaction log — every individual `spend()` call in order.
161
+ */
162
+ getTransactionLog(): SpendLogEntry[];
163
+ /**
164
+ * Current global ceiling (may differ from the original if `setCeiling()` was called).
165
+ */
166
+ getCeiling(): number;
167
+ /**
168
+ * Per-agent ceiling, or `undefined` if none was configured.
169
+ */
170
+ getPerAgentCeiling(): number | undefined;
171
+ /**
172
+ * Dynamically adjust the global ceiling.
173
+ *
174
+ * The new ceiling must be a positive finite number. It may be set below
175
+ * the current `totalSpent` (no previously approved spends are reversed, but
176
+ * future spends will be denied until tokens are freed by a `reset()`).
177
+ *
178
+ * @param ceiling New global ceiling.
179
+ */
180
+ setCeiling(ceiling: number): void;
181
+ /**
182
+ * Reset all spend counters and clear the transaction log.
183
+ *
184
+ * The global ceiling is preserved (its current value after any `setCeiling()`
185
+ * calls). After a reset `remaining() === getCeiling()`.
186
+ *
187
+ * The blackboard entry (if configured) is updated with the reset state.
188
+ */
189
+ reset(): void;
190
+ /**
191
+ * Restore budget state from the blackboard backend.
192
+ *
193
+ * Reads the entry stored under `budgetKey`, deserializes the snapshot, and
194
+ * replaces the current in-memory state. Useful when a node restarts and
195
+ * needs to recover its prior accumulated spend.
196
+ *
197
+ * No-op (returns `false`) when no blackboard is configured or no entry exists.
198
+ *
199
+ * @returns `true` if state was successfully loaded, `false` otherwise.
200
+ */
201
+ loadFromBlackboard(): boolean;
202
+ /** Serialize current state to the blackboard, if one is configured. */
203
+ private _persist;
204
+ }
205
+ //# sourceMappingURL=federated-budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federated-budget.d.ts","sourceRoot":"","sources":["../../lib/federated-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAM9D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;CACnB;AAiBD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAE/B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD;;;;;;GAMG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgC;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,OAAO,EAAE,sBAAsB;IAyB3C;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW;IA6CnD;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAItC;;OAEG;IACH,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAQrC;;OAEG;IACH,iBAAiB,IAAI,aAAa,EAAE;IAIpC;;OAEG;IACH,UAAU,IAAI,MAAM;IAIpB;;OAEG;IACH,kBAAkB,IAAI,MAAM,GAAG,SAAS;IAIxC;;;;;;;;OAQG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQjC;;;;;;;OAOG;IACH,KAAK,IAAI,IAAI;IAOb;;;;;;;;;;OAUG;IACH,kBAAkB,IAAI,OAAO;IAsB7B,uEAAuE;IACvE,OAAO,CAAC,QAAQ;CAcjB"}