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,275 @@
1
+ "use strict";
2
+ /**
3
+ * Federated Budget Tracking
4
+ *
5
+ * Tracks token spending across distributed agent swarms. Each `FederatedBudget`
6
+ * instance enforces a global ceiling shared among all agents that call `spend()`.
7
+ *
8
+ * When an optional `BlackboardBackend` is supplied, the budget state is written
9
+ * to the blackboard after every mutation. Wiring a `CrdtBackend` or `RedisBackend`
10
+ * as the underlying backend therefore gives automatic cross-node synchronization
11
+ * with no extra configuration.
12
+ *
13
+ * Architecture:
14
+ * - In-memory `spent` map keyed by `agentId` holds per-agent cumulative totals.
15
+ * - `spend()` is synchronous and enforces both the global ceiling and an optional
16
+ * per-agent ceiling in a single check.
17
+ * - A `blackboard` backend (if supplied) stores a JSON snapshot under `budgetKey`
18
+ * after every `spend()` / `reset()` / `setCeiling()` call so distributed nodes
19
+ * can read the latest state.
20
+ * - `loadFromBlackboard()` deserializes a previously saved snapshot so a
21
+ * restarted node can recover its prior accumulated spend.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { FederatedBudget } from 'network-ai';
26
+ *
27
+ * const budget = new FederatedBudget({ ceiling: 10_000 });
28
+ *
29
+ * budget.spend('agent-1', 3000); // { allowed: true, remaining: 7000 }
30
+ * budget.spend('agent-2', 8000); // { allowed: false, remaining: 7000 }
31
+ * budget.remaining(); // 7000
32
+ * budget.getSpendLog(); // { 'agent-1': 3000 }
33
+ * ```
34
+ *
35
+ * @example With blackboard persistence
36
+ * ```typescript
37
+ * import { CrdtBackend } from 'network-ai';
38
+ * import { FederatedBudget } from 'network-ai';
39
+ *
40
+ * const node = new CrdtBackend('node-a');
41
+ * const budget = new FederatedBudget({ ceiling: 50_000, blackboard: node });
42
+ *
43
+ * budget.spend('agent-1', 1000);
44
+ * // State is now stored in node under 'federated-budget'
45
+ * // Sync node to other CrdtBackend nodes to propagate the spend.
46
+ * ```
47
+ *
48
+ * @module FederatedBudget
49
+ * @version 1.0.0
50
+ * @license MIT
51
+ */
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ exports.FederatedBudget = void 0;
54
+ // ============================================================================
55
+ // FEDERATED BUDGET
56
+ // ============================================================================
57
+ /**
58
+ * Federated token-budget tracker for distributed agent swarms.
59
+ *
60
+ * Enforces a shared global ceiling across all agents and optionally an
61
+ * individual per-agent ceiling. State can be persisted to any
62
+ * `BlackboardBackend` for cross-node visibility.
63
+ */
64
+ class FederatedBudget {
65
+ _ceiling;
66
+ _dynamicCeiling;
67
+ _perAgentCeiling;
68
+ _spent = new Map();
69
+ _totalSpent = 0;
70
+ _log = [];
71
+ _blackboard;
72
+ _budgetKey;
73
+ _bbAgent;
74
+ constructor(options) {
75
+ if (typeof options.ceiling !== 'number' || options.ceiling <= 0 || !Number.isFinite(options.ceiling)) {
76
+ throw new RangeError('FederatedBudget: ceiling must be a positive finite number');
77
+ }
78
+ if (options.perAgentCeiling !== undefined &&
79
+ (typeof options.perAgentCeiling !== 'number' ||
80
+ options.perAgentCeiling <= 0 ||
81
+ !Number.isFinite(options.perAgentCeiling))) {
82
+ throw new RangeError('FederatedBudget: perAgentCeiling must be a positive finite number when provided');
83
+ }
84
+ this._ceiling = options.ceiling;
85
+ this._dynamicCeiling = options.ceiling;
86
+ this._perAgentCeiling = options.perAgentCeiling;
87
+ this._blackboard = options.blackboard;
88
+ this._budgetKey = options.budgetKey ?? 'federated-budget';
89
+ this._bbAgent = options.blackboardAgent ?? 'federated-budget-tracker';
90
+ }
91
+ // --------------------------------------------------------------------------
92
+ // PUBLIC API
93
+ // --------------------------------------------------------------------------
94
+ /**
95
+ * Attempt to spend `tokens` on behalf of `agentId`.
96
+ *
97
+ * The spend is allowed only when:
98
+ * 1. `totalSpent + tokens <= ceiling` (global ceiling not breached), AND
99
+ * 2. `agentSpent + tokens <= perAgentCeiling` if a per-agent ceiling is set.
100
+ *
101
+ * When allowed the internal counters are updated and the state is persisted
102
+ * to the blackboard (if configured).
103
+ *
104
+ * @param agentId Identifier of the spending agent. Must be a non-empty string.
105
+ * @param tokens Number of tokens to spend. Must be a positive integer.
106
+ * @returns `SpendResult` with `allowed`, `remaining`, and optional `deniedReason`.
107
+ */
108
+ spend(agentId, tokens) {
109
+ if (!agentId || typeof agentId !== 'string') {
110
+ throw new TypeError('FederatedBudget.spend: agentId must be a non-empty string');
111
+ }
112
+ if (typeof tokens !== 'number' || tokens <= 0 || !Number.isFinite(tokens)) {
113
+ throw new RangeError('FederatedBudget.spend: tokens must be a positive finite number');
114
+ }
115
+ const agentSpent = this._spent.get(agentId) ?? 0;
116
+ // Check per-agent ceiling first (lower ceiling wins)
117
+ if (this._perAgentCeiling !== undefined && agentSpent + tokens > this._perAgentCeiling) {
118
+ return {
119
+ allowed: false,
120
+ remaining: this.remaining(),
121
+ deniedReason: 'per_agent_ceiling',
122
+ };
123
+ }
124
+ // Check global ceiling
125
+ if (this._totalSpent + tokens > this._dynamicCeiling) {
126
+ return {
127
+ allowed: false,
128
+ remaining: this.remaining(),
129
+ deniedReason: 'global_ceiling',
130
+ };
131
+ }
132
+ // Commit
133
+ this._spent.set(agentId, agentSpent + tokens);
134
+ this._totalSpent += tokens;
135
+ this._log.push({
136
+ agentId,
137
+ tokens,
138
+ timestamp: new Date().toISOString(),
139
+ });
140
+ this._persist();
141
+ return {
142
+ allowed: true,
143
+ remaining: this.remaining(),
144
+ };
145
+ }
146
+ /**
147
+ * Remaining tokens in the global pool.
148
+ */
149
+ remaining() {
150
+ return Math.max(0, this._dynamicCeiling - this._totalSpent);
151
+ }
152
+ /**
153
+ * Total tokens spent across all agents.
154
+ */
155
+ getTotalSpent() {
156
+ return this._totalSpent;
157
+ }
158
+ /**
159
+ * Tokens spent by a specific agent. Returns `0` if the agent has no spend.
160
+ */
161
+ getAgentSpent(agentId) {
162
+ return this._spent.get(agentId) ?? 0;
163
+ }
164
+ /**
165
+ * Per-agent spend totals as a plain object: `{ agentId: totalTokens }`.
166
+ */
167
+ getSpendLog() {
168
+ const result = {};
169
+ for (const [id, total] of this._spent) {
170
+ result[id] = total;
171
+ }
172
+ return result;
173
+ }
174
+ /**
175
+ * Detailed transaction log — every individual `spend()` call in order.
176
+ */
177
+ getTransactionLog() {
178
+ return this._log.slice();
179
+ }
180
+ /**
181
+ * Current global ceiling (may differ from the original if `setCeiling()` was called).
182
+ */
183
+ getCeiling() {
184
+ return this._dynamicCeiling;
185
+ }
186
+ /**
187
+ * Per-agent ceiling, or `undefined` if none was configured.
188
+ */
189
+ getPerAgentCeiling() {
190
+ return this._perAgentCeiling;
191
+ }
192
+ /**
193
+ * Dynamically adjust the global ceiling.
194
+ *
195
+ * The new ceiling must be a positive finite number. It may be set below
196
+ * the current `totalSpent` (no previously approved spends are reversed, but
197
+ * future spends will be denied until tokens are freed by a `reset()`).
198
+ *
199
+ * @param ceiling New global ceiling.
200
+ */
201
+ setCeiling(ceiling) {
202
+ if (typeof ceiling !== 'number' || ceiling <= 0 || !Number.isFinite(ceiling)) {
203
+ throw new RangeError('FederatedBudget.setCeiling: ceiling must be a positive finite number');
204
+ }
205
+ this._dynamicCeiling = ceiling;
206
+ this._persist();
207
+ }
208
+ /**
209
+ * Reset all spend counters and clear the transaction log.
210
+ *
211
+ * The global ceiling is preserved (its current value after any `setCeiling()`
212
+ * calls). After a reset `remaining() === getCeiling()`.
213
+ *
214
+ * The blackboard entry (if configured) is updated with the reset state.
215
+ */
216
+ reset() {
217
+ this._spent.clear();
218
+ this._totalSpent = 0;
219
+ this._log.length = 0;
220
+ this._persist();
221
+ }
222
+ /**
223
+ * Restore budget state from the blackboard backend.
224
+ *
225
+ * Reads the entry stored under `budgetKey`, deserializes the snapshot, and
226
+ * replaces the current in-memory state. Useful when a node restarts and
227
+ * needs to recover its prior accumulated spend.
228
+ *
229
+ * No-op (returns `false`) when no blackboard is configured or no entry exists.
230
+ *
231
+ * @returns `true` if state was successfully loaded, `false` otherwise.
232
+ */
233
+ loadFromBlackboard() {
234
+ if (!this._blackboard)
235
+ return false;
236
+ const entry = this._blackboard.read(this._budgetKey);
237
+ if (!entry)
238
+ return false;
239
+ try {
240
+ const snapshot = JSON.parse(entry.value);
241
+ this._spent.clear();
242
+ for (const [id, total] of Object.entries(snapshot.spent)) {
243
+ this._spent.set(id, total);
244
+ }
245
+ this._totalSpent = snapshot.totalSpent;
246
+ this._dynamicCeiling = snapshot.ceiling;
247
+ return true;
248
+ }
249
+ catch {
250
+ return false;
251
+ }
252
+ }
253
+ // --------------------------------------------------------------------------
254
+ // PRIVATE HELPERS
255
+ // --------------------------------------------------------------------------
256
+ /** Serialize current state to the blackboard, if one is configured. */
257
+ _persist() {
258
+ if (!this._blackboard)
259
+ return;
260
+ const snapshot = {
261
+ ceiling: this._dynamicCeiling,
262
+ perAgentCeiling: this._perAgentCeiling,
263
+ spent: this.getSpendLog(),
264
+ totalSpent: this._totalSpent,
265
+ };
266
+ try {
267
+ this._blackboard.write(this._budgetKey, JSON.stringify(snapshot), this._bbAgent);
268
+ }
269
+ catch {
270
+ // Swallow persistence errors — the in-memory state remains authoritative.
271
+ }
272
+ }
273
+ }
274
+ exports.FederatedBudget = FederatedBudget;
275
+ //# sourceMappingURL=federated-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federated-budget.js","sourceRoot":"","sources":["../../lib/federated-budget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Test runner — executes all test suites sequentially as isolated child
3
+ * processes. Each suite is fully cleaned up before the next one starts,
4
+ * preventing memory accumulation that crashes VS Code's integrated terminal.
5
+ *
6
+ * Usage: npx ts-node run-tests.ts
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=run-tests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-tests.d.ts","sourceRoot":"","sources":["../run-tests.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /**
3
+ * Test runner — executes all test suites sequentially as isolated child
4
+ * processes. Each suite is fully cleaned up before the next one starts,
5
+ * preventing memory accumulation that crashes VS Code's integrated terminal.
6
+ *
7
+ * Usage: npx ts-node run-tests.ts
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const child_process_1 = require("child_process");
11
+ const path_1 = require("path");
12
+ const SUITES = [
13
+ 'test-standalone.ts',
14
+ 'test-security.ts',
15
+ 'test-adapters.ts',
16
+ 'test-priority.ts',
17
+ 'test-phase4.ts',
18
+ 'test-phase5.ts',
19
+ 'test-phase5b.ts',
20
+ 'test-phase5c.ts',
21
+ 'test-phase5d.ts',
22
+ 'test-phase5e.ts',
23
+ 'test-phase5f.ts',
24
+ ];
25
+ const WIDTH = 60;
26
+ const cwd = (0, path_1.resolve)(__dirname);
27
+ let totalPassed = 0;
28
+ let totalFailed = 0;
29
+ const results = [];
30
+ console.log('='.repeat(WIDTH));
31
+ console.log(' Network-AI Full Test Suite');
32
+ console.log('='.repeat(WIDTH));
33
+ for (const suite of SUITES) {
34
+ process.stdout.write(`\nRunning ${suite} ... `);
35
+ const result = (0, child_process_1.spawnSync)(process.execPath, // node
36
+ ['-e', `require('ts-node/register'); require('./${suite}')`], {
37
+ cwd,
38
+ encoding: 'utf8',
39
+ maxBuffer: 10 * 1024 * 1024, // 10 MB output buffer
40
+ env: {
41
+ ...process.env,
42
+ NODE_OPTIONS: '--max-old-space-size=512', // cap per-process RAM
43
+ },
44
+ });
45
+ // Count pass/fail markers — suites use either [PASS]/[FAIL] or [v]/[x]
46
+ const stdout = result.stdout ?? '';
47
+ const stderr = result.stderr ?? '';
48
+ const passed = (stdout.match(/\[PASS\]|\[v\]/g) ?? []).length;
49
+ const failed = (stdout.match(/\[FAIL\]|\[x\]/g) ?? []).length;
50
+ const ok = result.status === 0 && failed === 0;
51
+ totalPassed += passed;
52
+ totalFailed += failed;
53
+ results.push({ suite, passed, failed, ok });
54
+ if (ok) {
55
+ console.log(`OK (${passed} passed)`);
56
+ }
57
+ else {
58
+ console.log(`FAIL (${passed} passed, ${failed} failed)`);
59
+ // Print the last 20 lines of output for quick diagnosis
60
+ const lines = (stdout + stderr).split('\n').filter(Boolean);
61
+ lines.slice(-20).forEach(l => console.log(' ' + l));
62
+ }
63
+ }
64
+ console.log('\n' + '='.repeat(WIDTH));
65
+ console.log(` Results: ${totalPassed} passed, ${totalFailed} failed`);
66
+ console.log('='.repeat(WIDTH));
67
+ const allOk = results.every(r => r.ok);
68
+ if (allOk) {
69
+ console.log(`\nALL ${totalPassed} TESTS PASSED\n`);
70
+ }
71
+ else {
72
+ console.log('\nFAILED SUITES:');
73
+ results.filter(r => !r.ok).forEach(r => console.log(` - ${r.suite} (${r.failed} failed)`));
74
+ process.exit(1);
75
+ }
76
+ //# sourceMappingURL=run-tests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-tests.js","sourceRoot":"","sources":["../run-tests.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "network-ai",
3
- "version": "3.7.0",
3
+ "version": "3.8.0",
4
4
  "description": "AI agent orchestration framework for TypeScript/Node.js - plug-and-play multi-agent coordination with 12 frameworks (LangChain, AutoGen, CrewAI, OpenAI Assistants, LlamaIndex, Semantic Kernel, Haystack, DSPy, Agno, MCP, OpenClaw). Built-in security, swarm intelligence, and agentic workflow patterns.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -18,7 +18,9 @@
18
18
  "test:phase5b": "npx ts-node test-phase5b.ts",
19
19
  "test:phase5c": "npx ts-node test-phase5c.ts",
20
20
  "test:phase5d": "npx ts-node test-phase5d.ts",
21
- "test:all": "npx ts-node test-standalone.ts && npx ts-node test-security.ts && npx ts-node test-adapters.ts && npx ts-node test-priority.ts && npx ts-node test-phase4.ts && npx ts-node test-phase5.ts && npx ts-node test-phase5b.ts && npx ts-node test-phase5c.ts && npx ts-node test-phase5d.ts",
21
+ "test:phase5e": "npx ts-node test-phase5e.ts",
22
+ "test:phase5f": "npx ts-node test-phase5f.ts",
23
+ "test:all": "npx ts-node run-tests.ts",
22
24
  "setup": "npx ts-node setup.ts",
23
25
  "setup:check": "npx ts-node setup.ts --check",
24
26
  "setup:example": "npx ts-node setup.ts --example",