network-ai 3.0.3 → 3.1.2

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.js CHANGED
@@ -6,11 +6,11 @@
6
6
  * task decomposition, permission management, and shared blackboard coordination.
7
7
  *
8
8
  * @module SwarmOrchestrator
9
- * @version 3.0.0
9
+ * @version 3.1.0
10
10
  * @license MIT
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.CustomAdapter = exports.MCPAdapter = exports.CrewAIAdapter = exports.AutoGenAdapter = exports.LangChainAdapter = exports.OpenClawAdapter = exports.BaseAdapter = exports.AdapterRegistry = exports.QualityGateAgent = exports.BlackboardValidator = exports.TaskDecomposer = exports.AuthGuardian = exports.SharedBlackboard = exports.SwarmOrchestrator = void 0;
13
+ exports.TimeoutError = exports.ParallelLimitError = exports.AdapterNotInitializedError = exports.AdapterNotFoundError = exports.AdapterAlreadyRegisteredError = exports.ConflictError = exports.LockAcquisitionError = exports.ValidationError = exports.NamespaceViolationError = exports.IdentityVerificationError = exports.NetworkAIError = exports.LogLevel = exports.Logger = exports.CustomAdapter = exports.MCPAdapter = exports.CrewAIAdapter = exports.AutoGenAdapter = exports.LangChainAdapter = exports.OpenClawAdapter = exports.BaseAdapter = exports.AdapterRegistry = exports.QualityGateAgent = exports.BlackboardValidator = exports.TaskDecomposer = exports.AuthGuardian = exports.SharedBlackboard = exports.SwarmOrchestrator = void 0;
14
14
  exports.createSwarmOrchestrator = createSwarmOrchestrator;
15
15
  const fs_1 = require("fs");
16
16
  const path_1 = require("path");
@@ -19,6 +19,9 @@ const adapter_registry_1 = require("./adapters/adapter-registry");
19
19
  const security_1 = require("./security");
20
20
  const locked_blackboard_1 = require("./lib/locked-blackboard");
21
21
  const blackboard_validator_1 = require("./lib/blackboard-validator");
22
+ const logger_1 = require("./lib/logger");
23
+ const errors_1 = require("./lib/errors");
24
+ const log = logger_1.Logger.create('SwarmOrchestrator');
22
25
  // ============================================================================
23
26
  // CONFIGURATION
24
27
  // ============================================================================
@@ -71,11 +74,29 @@ const DEFAULT_AGENT_TRUST = [
71
74
  // BLACKBOARD MANAGEMENT -- Secured with LockedBlackboard, identity verification,
72
75
  // namespace scoping, value validation, and input sanitization
73
76
  // ============================================================================
77
+ /**
78
+ * Namespace-scoped, identity-verified shared state for multi-agent coordination.
79
+ *
80
+ * Every write is identity-verified (agent token), namespace-checked,
81
+ * size-validated, input-sanitized, and atomically persisted through
82
+ * {@link LockedBlackboard}.
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const bb = new SharedBlackboard('./workspace');
87
+ * bb.registerAgent('analyst', 'secret-token', ['task:', 'analytics:']);
88
+ * bb.write('task:revenue', { q4: 42_000 }, 'analyst', 3600, 'secret-token');
89
+ * const entry = bb.read('task:revenue');
90
+ * ```
91
+ */
74
92
  class SharedBlackboard {
75
93
  backend;
76
94
  agentTokens = new Map(); // agentId -> verified token
77
95
  agentNamespaces = new Map(); // agentId -> allowed prefixes
78
96
  constructor(basePath) {
97
+ if (!basePath || typeof basePath !== 'string' || basePath.trim() === '') {
98
+ throw new errors_1.ValidationError('basePath must be a non-empty string');
99
+ }
79
100
  this.backend = new locked_blackboard_1.LockedBlackboard(basePath);
80
101
  }
81
102
  /**
@@ -84,6 +105,15 @@ class SharedBlackboard {
84
105
  * verifying their identity through the AuthGuardian.
85
106
  */
86
107
  registerAgent(agentId, verificationToken, allowedNamespaces = ['*']) {
108
+ if (!agentId || typeof agentId !== 'string' || agentId.trim() === '') {
109
+ throw new errors_1.ValidationError('agentId must be a non-empty string');
110
+ }
111
+ if (!verificationToken || typeof verificationToken !== 'string') {
112
+ throw new errors_1.ValidationError('verificationToken must be a non-empty string');
113
+ }
114
+ if (!Array.isArray(allowedNamespaces)) {
115
+ throw new errors_1.ValidationError('allowedNamespaces must be an array of strings');
116
+ }
87
117
  this.agentTokens.set(agentId, verificationToken);
88
118
  this.agentNamespaces.set(agentId, allowedNamespaces);
89
119
  }
@@ -131,7 +161,17 @@ class SharedBlackboard {
131
161
  // Keys must be safe for markdown headings -- no #, newlines, or markdown syntax
132
162
  return key.replace(/[#\n\r|`]/g, '_').slice(0, 256);
133
163
  }
164
+ /**
165
+ * Read an entry from the blackboard by key.
166
+ *
167
+ * @param key - The entry key to look up
168
+ * @returns The entry, or `null` if not found or expired
169
+ * @throws {@link ValidationError} if `key` is not a non-empty string
170
+ */
134
171
  read(key) {
172
+ if (!key || typeof key !== 'string') {
173
+ throw new errors_1.ValidationError('key must be a non-empty string');
174
+ }
135
175
  const entry = this.backend.read(key);
136
176
  if (!entry)
137
177
  return null;
@@ -158,18 +198,18 @@ class SharedBlackboard {
158
198
  write(key, value, sourceAgent, ttl, agentToken) {
159
199
  // 1. Verify agent identity
160
200
  if (!this.verifyAgent(sourceAgent, agentToken)) {
161
- throw new Error(`[Blackboard] Identity verification failed for agent '${sourceAgent}'`);
201
+ throw new errors_1.IdentityVerificationError(sourceAgent);
162
202
  }
163
203
  // 2. Namespace check
164
204
  if (!this.canAccessKey(sourceAgent, key)) {
165
- throw new Error(`[Blackboard] Agent '${sourceAgent}' not allowed to write to key '${key}'`);
205
+ throw new errors_1.NamespaceViolationError(sourceAgent, key);
166
206
  }
167
207
  // 3. Sanitize key
168
208
  const safeKey = this.sanitizeKey(key);
169
209
  // 4. Validate value size/structure
170
210
  const validation = this.validateValue(value);
171
211
  if (!validation.valid) {
172
- throw new Error(`[Blackboard] Value validation failed: ${validation.reason}`);
212
+ throw new errors_1.ValidationError(validation.reason);
173
213
  }
174
214
  // 5. Sanitize value -- strip injection payloads from string content
175
215
  let sanitizedValue;
@@ -190,6 +230,10 @@ class SharedBlackboard {
190
230
  ttl: entry.ttl,
191
231
  };
192
232
  }
233
+ /**
234
+ * Check whether a key exists on the blackboard (not expired).
235
+ * @param key - The entry key to check
236
+ */
193
237
  exists(key) {
194
238
  return this.read(key) !== null;
195
239
  }
@@ -215,6 +259,9 @@ class SharedBlackboard {
215
259
  * Prevents data leakage between agents.
216
260
  */
217
261
  getScopedSnapshot(agentId) {
262
+ if (!agentId || typeof agentId !== 'string') {
263
+ throw new errors_1.ValidationError('agentId must be a non-empty string');
264
+ }
218
265
  const full = this.getSnapshot();
219
266
  const scoped = {};
220
267
  for (const [key, entry] of Object.entries(full)) {
@@ -243,6 +290,29 @@ exports.SharedBlackboard = SharedBlackboard;
243
290
  // Integrates with SecureSwarmGateway for HMAC tokens, rate limiting,
244
291
  // input sanitization, and cryptographic audit logs.
245
292
  // ============================================================================
293
+ /**
294
+ * Universal permission wall for multi-agent systems.
295
+ *
296
+ * Evaluates permission requests using a weighted formula of justification
297
+ * quality (40%), agent trust level (30%), and risk score (30%).
298
+ * Resource types, risk profiles, trust levels, and restrictions are all
299
+ * configurable — works for coding, finance, DevOps, or any domain.
300
+ *
301
+ * @example
302
+ * ```typescript
303
+ * const guardian = new AuthGuardian({
304
+ * trustLevels: [{ agentId: 'analyst', trustLevel: 0.8 }],
305
+ * resourceProfiles: { CUSTOM_API: { baseRisk: 0.5, defaultRestrictions: ['audit_required'] } },
306
+ * });
307
+ *
308
+ * const grant = await guardian.requestPermission(
309
+ * 'analyst', 'CUSTOM_API', 'Need to fetch Q4 revenue data for report', 'read'
310
+ * );
311
+ * if (grant.granted) {
312
+ * // Use grant.grantToken to prove authorization
313
+ * }
314
+ * ```
315
+ */
246
316
  class AuthGuardian {
247
317
  activeGrants = new Map();
248
318
  agentTrustLevels = new Map();
@@ -273,12 +343,33 @@ class AuthGuardian {
273
343
  * Makes the system extensible for any domain.
274
344
  */
275
345
  registerResourceType(name, profile) {
346
+ if (!name || typeof name !== 'string' || name.trim() === '') {
347
+ throw new errors_1.ValidationError('resource name must be a non-empty string');
348
+ }
349
+ if (!profile || typeof profile !== 'object' || typeof profile.baseRisk !== 'number') {
350
+ throw new errors_1.ValidationError('profile must be an object with a numeric baseRisk');
351
+ }
352
+ if (profile.baseRisk < 0 || profile.baseRisk > 1) {
353
+ throw new errors_1.ValidationError('profile.baseRisk must be between 0 and 1');
354
+ }
355
+ if (!Array.isArray(profile.defaultRestrictions)) {
356
+ throw new errors_1.ValidationError('profile.defaultRestrictions must be an array');
357
+ }
276
358
  this.resourceProfiles.set(name, profile);
277
359
  }
278
360
  /**
279
361
  * Register or update an agent's trust configuration at runtime.
280
362
  */
281
363
  registerAgentTrust(config) {
364
+ if (!config || typeof config !== 'object') {
365
+ throw new errors_1.ValidationError('config must be an object');
366
+ }
367
+ if (!config.agentId || typeof config.agentId !== 'string' || config.agentId.trim() === '') {
368
+ throw new errors_1.ValidationError('config.agentId must be a non-empty string');
369
+ }
370
+ if (typeof config.trustLevel !== 'number' || config.trustLevel < 0 || config.trustLevel > 1) {
371
+ throw new errors_1.ValidationError('config.trustLevel must be a number between 0 and 1');
372
+ }
282
373
  this.agentTrustLevels.set(config.agentId, config.trustLevel);
283
374
  this.agentTrustConfigs.set(config.agentId, config);
284
375
  this.persistTrustToDisk();
@@ -288,6 +379,15 @@ class AuthGuardian {
288
379
  * resourceType is now a free string -- validated against registered profiles.
289
380
  */
290
381
  async requestPermission(agentId, resourceType, justification, scope) {
382
+ if (!agentId || typeof agentId !== 'string') {
383
+ throw new errors_1.ValidationError('agentId must be a non-empty string');
384
+ }
385
+ if (!resourceType || typeof resourceType !== 'string') {
386
+ throw new errors_1.ValidationError('resourceType must be a non-empty string');
387
+ }
388
+ if (!justification || typeof justification !== 'string') {
389
+ throw new errors_1.ValidationError('justification must be a non-empty string');
390
+ }
291
391
  // Sanitize inputs
292
392
  let safeAgentId;
293
393
  let safeJustification;
@@ -346,7 +446,15 @@ class AuthGuardian {
346
446
  restrictions: evaluation.restrictions,
347
447
  };
348
448
  }
449
+ /**
450
+ * Validate a grant token and return `true` if it is active and not expired.
451
+ *
452
+ * @param token - The grant token to validate
453
+ * @returns `true` if the token is valid, `false` otherwise
454
+ */
349
455
  validateToken(token) {
456
+ if (!token || typeof token !== 'string')
457
+ return false;
350
458
  const grant = this.activeGrants.get(token);
351
459
  if (!grant)
352
460
  return false;
@@ -360,7 +468,16 @@ class AuthGuardian {
360
468
  * Validate a token and return the bound restrictions and scope.
361
469
  * Used to enforce restrictions at the point of use.
362
470
  */
471
+ /**
472
+ * Validate a token and return the full grant object (including restrictions
473
+ * and scope) for point-of-use enforcement.
474
+ *
475
+ * @param token - The grant token to validate
476
+ * @returns The grant details, or `null` if invalid/expired
477
+ */
363
478
  validateTokenWithGrant(token) {
479
+ if (!token || typeof token !== 'string')
480
+ return null;
364
481
  const grant = this.activeGrants.get(token);
365
482
  if (!grant)
366
483
  return null;
@@ -374,7 +491,18 @@ class AuthGuardian {
374
491
  * Enforce restrictions on an operation. Returns an error string if
375
492
  * the operation violates any restriction, or null if allowed.
376
493
  */
494
+ /**
495
+ * Enforce restrictions on an operation. Returns an error string if
496
+ * the operation violates any restriction, or `null` if all restrictions pass.
497
+ *
498
+ * @param grantToken - The grant token authorizing the operation
499
+ * @param operation - Description of the operation to check against restrictions
500
+ * @returns Error message string if a restriction is violated, or `null` if allowed
501
+ */
377
502
  enforceRestrictions(grantToken, operation) {
503
+ if (!grantToken || typeof grantToken !== 'string') {
504
+ return 'Invalid or expired grant token';
505
+ }
378
506
  const grant = this.validateTokenWithGrant(grantToken);
379
507
  if (!grant)
380
508
  return 'Invalid or expired grant token';
@@ -422,6 +550,12 @@ class AuthGuardian {
422
550
  }
423
551
  return null; // All restrictions passed
424
552
  }
553
+ /**
554
+ * Revoke a grant token, immediately invalidating it.
555
+ * Silently no-ops if the token doesn't exist.
556
+ *
557
+ * @param token - The grant token to revoke
558
+ */
425
559
  revokeToken(token) {
426
560
  this.activeGrants.delete(token);
427
561
  this.log('permission_revoked', { token });
@@ -558,6 +692,10 @@ class AuthGuardian {
558
692
  // Non-fatal -- log is also in memory
559
693
  }
560
694
  }
695
+ /**
696
+ * Get all active (non-expired) permission grants.
697
+ * Automatically cleans up expired grants before returning.
698
+ */
561
699
  getActiveGrants() {
562
700
  // Clean expired grants
563
701
  const now = new Date();
@@ -568,6 +706,10 @@ class AuthGuardian {
568
706
  }
569
707
  return Array.from(this.activeGrants.values());
570
708
  }
709
+ /**
710
+ * Get the full audit log of permission decisions.
711
+ * Returns a defensive copy.
712
+ */
571
713
  getAuditLog() {
572
714
  return [...this.auditLog];
573
715
  }
@@ -581,6 +723,8 @@ class AuthGuardian {
581
723
  * Get the allowed namespaces for an agent (used by blackboard scoping).
582
724
  */
583
725
  getAgentNamespaces(agentId) {
726
+ if (!agentId || typeof agentId !== 'string')
727
+ return ['task:'];
584
728
  const config = this.agentTrustConfigs.get(agentId);
585
729
  return config?.allowedNamespaces ?? ['task:'];
586
730
  }
@@ -628,11 +772,28 @@ exports.AuthGuardian = AuthGuardian;
628
772
  // ============================================================================
629
773
  // TASK DECOMPOSITION ENGINE
630
774
  // ============================================================================
775
+ /**
776
+ * Decomposes complex tasks into parallel sub-agent executions.
777
+ *
778
+ * Supports four synthesis strategies (`merge`, `vote`, `chain`, `first-success`)
779
+ * and caches results on the blackboard to avoid redundant work.
780
+ * Routes each sub-task through the {@link AdapterRegistry} so any
781
+ * registered framework can participate.
782
+ */
631
783
  class TaskDecomposer {
632
784
  blackboard;
633
785
  authGuardian;
634
786
  adapterRegistry;
635
787
  constructor(blackboard, authGuardian, adapterRegistry) {
788
+ if (!blackboard || !(blackboard instanceof SharedBlackboard)) {
789
+ throw new errors_1.ValidationError('blackboard must be an instance of SharedBlackboard');
790
+ }
791
+ if (!authGuardian || !(authGuardian instanceof AuthGuardian)) {
792
+ throw new errors_1.ValidationError('authGuardian must be an instance of AuthGuardian');
793
+ }
794
+ if (!adapterRegistry || !(adapterRegistry instanceof adapter_registry_1.AdapterRegistry)) {
795
+ throw new errors_1.ValidationError('adapterRegistry must be an instance of AdapterRegistry');
796
+ }
636
797
  this.blackboard = blackboard;
637
798
  this.authGuardian = authGuardian;
638
799
  this.adapterRegistry = adapterRegistry;
@@ -643,10 +804,18 @@ class TaskDecomposer {
643
804
  * into manageable parallel executions
644
805
  */
645
806
  async executeParallel(tasks, synthesisStrategy = 'merge', context) {
807
+ if (!tasks || !Array.isArray(tasks)) {
808
+ throw new errors_1.ValidationError('tasks must be an array');
809
+ }
810
+ if (tasks.length === 0) {
811
+ throw new errors_1.ValidationError('tasks array must not be empty');
812
+ }
813
+ if (!context || typeof context !== 'object' || !context.agentId) {
814
+ throw new errors_1.ValidationError('context is required and must include agentId');
815
+ }
646
816
  // Enforce maximum parallel agent limit
647
817
  if (tasks.length > CONFIG.maxParallelAgents) {
648
- throw new Error(`Cannot spawn ${tasks.length} agents. Maximum is ${CONFIG.maxParallelAgents}. ` +
649
- `Decompose further or use 'chain' strategy.`);
818
+ throw new errors_1.ParallelLimitError(tasks.length, CONFIG.maxParallelAgents);
650
819
  }
651
820
  const startTime = Date.now();
652
821
  const individualResults = [];
@@ -842,9 +1011,31 @@ exports.TaskDecomposer = TaskDecomposer;
842
1011
  // ============================================================================
843
1012
  // SWARM ORCHESTRATOR - MAIN SKILL IMPLEMENTATION
844
1013
  // ============================================================================
1014
+ /**
1015
+ * The main orchestrator class — coordinates agents, permissions, blackboard,
1016
+ * quality gates, and adapter routing in a single entry point.
1017
+ *
1018
+ * Implements the OpenClaw skill interface for backward compatibility and
1019
+ * can also be used standalone via {@link createSwarmOrchestrator}.
1020
+ *
1021
+ * @example
1022
+ * ```typescript
1023
+ * import { createSwarmOrchestrator, LangChainAdapter } from 'network-ai';
1024
+ *
1025
+ * const orchestrator = createSwarmOrchestrator({
1026
+ * adapters: [{ adapter: new LangChainAdapter() }],
1027
+ * trustLevels: [{ agentId: 'my-agent', trustLevel: 0.8 }],
1028
+ * });
1029
+ *
1030
+ * const result = await orchestrator.execute('delegate_task', {
1031
+ * targetAgent: 'my-agent',
1032
+ * taskPayload: { instruction: 'Summarize the quarterly report' },
1033
+ * }, { agentId: 'orchestrator' });
1034
+ * ```
1035
+ */
845
1036
  class SwarmOrchestrator {
846
1037
  name = 'SwarmOrchestrator';
847
- version = '3.0.0';
1038
+ version = '3.1.0';
848
1039
  blackboard;
849
1040
  authGuardian;
850
1041
  taskDecomposer;
@@ -854,6 +1045,12 @@ class SwarmOrchestrator {
854
1045
  /** The adapter registry -- routes requests to the right agent framework */
855
1046
  adapters;
856
1047
  constructor(workspacePath = process.cwd(), adapterRegistry, options) {
1048
+ if (workspacePath !== undefined && typeof workspacePath !== 'string') {
1049
+ throw new errors_1.ValidationError('workspacePath must be a string');
1050
+ }
1051
+ if (workspacePath !== undefined && workspacePath.trim() === '') {
1052
+ throw new errors_1.ValidationError('workspacePath must not be empty');
1053
+ }
857
1054
  this.blackboard = new SharedBlackboard(workspacePath);
858
1055
  this.authGuardian = new AuthGuardian({
859
1056
  trustLevels: options?.trustLevels,
@@ -875,6 +1072,12 @@ class SwarmOrchestrator {
875
1072
  * This is the plug-and-play entry point.
876
1073
  */
877
1074
  async addAdapter(adapter, config = {}) {
1075
+ if (!adapter || typeof adapter !== 'object') {
1076
+ throw new errors_1.ValidationError('adapter is required and must be an object');
1077
+ }
1078
+ if (typeof adapter.name !== 'string' || adapter.name.trim() === '') {
1079
+ throw new errors_1.ValidationError('adapter.name must be a non-empty string');
1080
+ }
878
1081
  await this.adapters.addAdapter(adapter, config);
879
1082
  }
880
1083
  /**
@@ -883,6 +1086,36 @@ class SwarmOrchestrator {
883
1086
  * input sanitization, rate limiting, and agent ID validation.
884
1087
  */
885
1088
  async execute(action, params, context) {
1089
+ if (!action || typeof action !== 'string') {
1090
+ return {
1091
+ success: false,
1092
+ error: {
1093
+ code: 'INVALID_PARAMS',
1094
+ message: 'action is required and must be a non-empty string',
1095
+ recoverable: false,
1096
+ },
1097
+ };
1098
+ }
1099
+ if (!params || typeof params !== 'object' || Array.isArray(params)) {
1100
+ return {
1101
+ success: false,
1102
+ error: {
1103
+ code: 'INVALID_PARAMS',
1104
+ message: 'params is required and must be a plain object',
1105
+ recoverable: false,
1106
+ },
1107
+ };
1108
+ }
1109
+ if (!context || typeof context !== 'object' || !context.agentId || typeof context.agentId !== 'string') {
1110
+ return {
1111
+ success: false,
1112
+ error: {
1113
+ code: 'INVALID_PARAMS',
1114
+ message: 'context is required and must include a non-empty agentId string',
1115
+ recoverable: false,
1116
+ },
1117
+ };
1118
+ }
886
1119
  const traceId = (0, crypto_1.randomUUID)();
887
1120
  // P0: Route through SecureSwarmGateway -- sanitization + rate limiting
888
1121
  const gatewayResult = await this.gateway.handleSecureRequest(context.agentId, action, params);
@@ -1343,13 +1576,20 @@ class SwarmOrchestrator {
1343
1576
  }
1344
1577
  timeoutPromise(ms) {
1345
1578
  return new Promise((_, reject) => {
1346
- setTimeout(() => reject(new Error(`Operation timed out after ${ms}ms`)), ms);
1579
+ setTimeout(() => reject(new errors_1.TimeoutError(ms)), ms);
1347
1580
  });
1348
1581
  }
1349
1582
  /**
1350
1583
  * Register an agent with the swarm
1351
1584
  */
1352
1585
  registerAgent(agentId, status = 'available') {
1586
+ if (!agentId || typeof agentId !== 'string' || agentId.trim() === '') {
1587
+ throw new errors_1.ValidationError('agentId must be a non-empty string');
1588
+ }
1589
+ const validStatuses = ['available', 'busy', 'waiting_auth', 'offline'];
1590
+ if (!validStatuses.includes(status)) {
1591
+ throw new errors_1.ValidationError(`status must be one of: ${validStatuses.join(', ')}`);
1592
+ }
1353
1593
  this.agentRegistry.set(agentId, {
1354
1594
  agentId,
1355
1595
  status,
@@ -1361,6 +1601,9 @@ class SwarmOrchestrator {
1361
1601
  * Update agent status
1362
1602
  */
1363
1603
  updateAgentStatus(agentId, status, currentTask) {
1604
+ if (!agentId || typeof agentId !== 'string' || agentId.trim() === '') {
1605
+ throw new errors_1.ValidationError('agentId must be a non-empty string');
1606
+ }
1364
1607
  const existing = this.agentRegistry.get(agentId);
1365
1608
  if (existing) {
1366
1609
  existing.status = status;
@@ -1396,6 +1639,23 @@ var mcp_adapter_1 = require("./adapters/mcp-adapter");
1396
1639
  Object.defineProperty(exports, "MCPAdapter", { enumerable: true, get: function () { return mcp_adapter_1.MCPAdapter; } });
1397
1640
  var custom_adapter_1 = require("./adapters/custom-adapter");
1398
1641
  Object.defineProperty(exports, "CustomAdapter", { enumerable: true, get: function () { return custom_adapter_1.CustomAdapter; } });
1642
+ // Logger
1643
+ var logger_2 = require("./lib/logger");
1644
+ Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_2.Logger; } });
1645
+ Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_2.LogLevel; } });
1646
+ // Typed errors
1647
+ var errors_2 = require("./lib/errors");
1648
+ Object.defineProperty(exports, "NetworkAIError", { enumerable: true, get: function () { return errors_2.NetworkAIError; } });
1649
+ Object.defineProperty(exports, "IdentityVerificationError", { enumerable: true, get: function () { return errors_2.IdentityVerificationError; } });
1650
+ Object.defineProperty(exports, "NamespaceViolationError", { enumerable: true, get: function () { return errors_2.NamespaceViolationError; } });
1651
+ Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return errors_2.ValidationError; } });
1652
+ Object.defineProperty(exports, "LockAcquisitionError", { enumerable: true, get: function () { return errors_2.LockAcquisitionError; } });
1653
+ Object.defineProperty(exports, "ConflictError", { enumerable: true, get: function () { return errors_2.ConflictError; } });
1654
+ Object.defineProperty(exports, "AdapterAlreadyRegisteredError", { enumerable: true, get: function () { return errors_2.AdapterAlreadyRegisteredError; } });
1655
+ Object.defineProperty(exports, "AdapterNotFoundError", { enumerable: true, get: function () { return errors_2.AdapterNotFoundError; } });
1656
+ Object.defineProperty(exports, "AdapterNotInitializedError", { enumerable: true, get: function () { return errors_2.AdapterNotInitializedError; } });
1657
+ Object.defineProperty(exports, "ParallelLimitError", { enumerable: true, get: function () { return errors_2.ParallelLimitError; } });
1658
+ Object.defineProperty(exports, "TimeoutError", { enumerable: true, get: function () { return errors_2.TimeoutError; } });
1399
1659
  /**
1400
1660
  * Factory function for creating a configured SwarmOrchestrator instance.
1401
1661
  *
@@ -1405,7 +1665,34 @@ Object.defineProperty(exports, "CustomAdapter", { enumerable: true, get: functio
1405
1665
  * adapters: [{ adapter: new LangChainAdapter(), config: {} }],
1406
1666
  * });
1407
1667
  */
1668
+ /**
1669
+ * Factory function for creating a fully configured {@link SwarmOrchestrator}.
1670
+ *
1671
+ * Accepts optional configuration for adapters, trust levels, resource profiles,
1672
+ * quality gate settings, and runtime overrides.
1673
+ *
1674
+ * @param config - Optional configuration object. Pass `undefined` for all defaults.
1675
+ * @returns A ready-to-use SwarmOrchestrator instance.
1676
+ *
1677
+ * @example
1678
+ * ```typescript
1679
+ * import { createSwarmOrchestrator, LangChainAdapter } from 'network-ai';
1680
+ *
1681
+ * // Minimal
1682
+ * const orc = createSwarmOrchestrator();
1683
+ *
1684
+ * // With adapters and trust
1685
+ * const orc2 = createSwarmOrchestrator({
1686
+ * adapters: [{ adapter: new LangChainAdapter() }],
1687
+ * trustLevels: [{ agentId: 'analyst', trustLevel: 0.8 }],
1688
+ * qualityThreshold: 0.7,
1689
+ * });
1690
+ * ```
1691
+ */
1408
1692
  function createSwarmOrchestrator(config) {
1693
+ if (config !== undefined && (typeof config !== 'object' || config === null || Array.isArray(config))) {
1694
+ throw new errors_1.ValidationError('config must be a plain object');
1695
+ }
1409
1696
  if (config) {
1410
1697
  const { adapters: adapterList, adapterRegistry, trustLevels, resourceProfiles, validationConfig, qualityThreshold, aiReviewCallback, ...rest } = config;
1411
1698
  Object.assign(CONFIG, rest);
@@ -1419,7 +1706,7 @@ function createSwarmOrchestrator(config) {
1419
1706
  });
1420
1707
  // Initialize adapters if provided
1421
1708
  if (adapterList) {
1422
- Promise.all(adapterList.map(({ adapter, config: adapterConfig }) => orchestrator.addAdapter(adapter, adapterConfig ?? {}))).catch(err => console.error('[SwarmOrchestrator] Adapter init error:', err));
1709
+ Promise.all(adapterList.map(({ adapter, config: adapterConfig }) => orchestrator.addAdapter(adapter, adapterConfig ?? {}))).catch(err => log.error('Adapter init error', { error: err instanceof Error ? err.message : String(err) }));
1423
1710
  }
1424
1711
  return orchestrator;
1425
1712
  }