Skip to content

Commit f335731

Browse files
author
jovanSAPFIONEER
committed
v3.1.0: Phase 2 - Trust (structured logging, typed errors, input validation, JSDoc, audit integration)
1 parent e82286c commit f335731

File tree

13 files changed

+1095
-182
lines changed

13 files changed

+1095
-182
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ All notable changes to Network-AI will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [3.1.0] - 2026-02-16
9+
10+
### Added -- Phase 2: Trust
11+
- **Structured Logging** -- `Logger` class with 4 severity levels (DEBUG/INFO/WARN/ERROR) + SILENT, module-scoped instances via `Logger.create()`, pluggable transports
12+
- **Typed Error Hierarchy** -- `NetworkAIError` base class + 10 specific error subclasses (`AdapterError`, `BlackboardError`, `SecurityError`, `ValidationError`, `LockError`, `TimeoutError`, `PermissionError`, `ConfigurationError`, `AgentError`, `OrchestratorError`)
13+
- **Runtime API Input Validation** -- Guards on 20+ public entry points (`SwarmOrchestrator`, `SharedBlackboard`, `AuthGuardian`, `TaskDecomposer`, `AdapterRegistry`) with descriptive `ValidationError` throws
14+
- **Comprehensive JSDoc** -- Documentation on all exported interfaces (12+), classes (13+), and public methods (8+) with `@example`, `@param`, `@returns`, `@throws` tags
15+
- **Unified Lock + Audit Integration** -- `LockedBlackboard` now accepts an optional `SecureAuditLogger`; `write()` and `delete()` emit structured audit events (lock holder, duration, key, version, success/failure)
16+
17+
### Stats
18+
- 251 tests passing (79 + 33 + 139)
19+
- 0 compile errors
20+
821
## [3.0.3] - 2026-02-15
922

1023
### Security Fix

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
**The plug-and-play AI agent orchestrator for TypeScript/Node.js -- connect 12 agent frameworks with zero glue code**
44

5-
[![Release](https://img.shields.io/badge/release-v3.0.3-blue.svg)](https://github.com/jovanSAPFIONEER/Network-AI/releases)
5+
[![Release](https://img.shields.io/badge/release-v3.1.0-blue.svg)](https://github.com/jovanSAPFIONEER/Network-AI/releases)
66
[![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org)
77
[![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178C6.svg)](https://typescriptlang.org)
88
[![Python](https://img.shields.io/badge/python-3.9+-green.svg)](https://python.org)

adapters/adapter-registry.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,29 @@ import type {
2222
AdapterEventHandler,
2323
AdapterEventType,
2424
} from '../types/agent-adapter';
25+
import { AdapterAlreadyRegisteredError, AdapterNotFoundError, ValidationError } from '../lib/errors';
2526

27+
/**
28+
* Central registry that manages multiple agent framework adapters and
29+
* routes execution requests to the correct one.
30+
*
31+
* Supports pattern-based routing, automatic prefix detection, default
32+
* adapter fallback, agent caching, unified discovery, and lifecycle events.
33+
*
34+
* @example
35+
* ```typescript
36+
* import { AdapterRegistry, LangChainAdapter, CustomAdapter } from 'network-ai';
37+
*
38+
* const registry = new AdapterRegistry();
39+
* await registry.addAdapter(new LangChainAdapter());
40+
* await registry.addAdapter(new CustomAdapter());
41+
*
42+
* // Route by prefix: "lc:research" -> LangChainAdapter
43+
* registry.addRoute({ pattern: 'lc:*', adapterName: 'langchain' });
44+
*
45+
* const result = await registry.executeAgent('lc:research', payload, context);
46+
* ```
47+
*/
2648
export class AdapterRegistry {
2749
private adapters: Map<string, IAgentAdapter> = new Map();
2850
private routes: AdapterRoute[] = [];
@@ -46,8 +68,14 @@ export class AdapterRegistry {
4668
* Call this for each agent framework you want to support.
4769
*/
4870
registerAdapter(adapter: IAgentAdapter): void {
71+
if (!adapter || typeof adapter !== 'object') {
72+
throw new ValidationError('adapter is required and must be an object');
73+
}
74+
if (typeof adapter.name !== 'string' || adapter.name.trim() === '') {
75+
throw new ValidationError('adapter.name must be a non-empty string');
76+
}
4977
if (this.adapters.has(adapter.name)) {
50-
throw new Error(`Adapter "${adapter.name}" is already registered`);
78+
throw new AdapterAlreadyRegisteredError(adapter.name);
5179
}
5280
this.adapters.set(adapter.name, adapter);
5381
this.emit('adapter:registered', adapter.name);
@@ -57,9 +85,12 @@ export class AdapterRegistry {
5785
* Initialize a registered adapter with its configuration
5886
*/
5987
async initializeAdapter(adapterName: string, config: AdapterConfig = {}): Promise<void> {
88+
if (!adapterName || typeof adapterName !== 'string') {
89+
throw new ValidationError('adapterName must be a non-empty string');
90+
}
6091
const adapter = this.adapters.get(adapterName);
6192
if (!adapter) {
62-
throw new Error(`Adapter "${adapterName}" is not registered`);
93+
throw new AdapterNotFoundError(adapterName);
6394
}
6495
await adapter.initialize(config);
6596
this.emit('adapter:initialized', adapterName);
@@ -112,7 +143,7 @@ export class AdapterRegistry {
112143
*/
113144
setDefaultAdapter(adapterName: string): void {
114145
if (!this.adapters.has(adapterName)) {
115-
throw new Error(`Adapter "${adapterName}" is not registered`);
146+
throw new AdapterNotFoundError(adapterName);
116147
}
117148
this.defaultAdapterName = adapterName;
118149
}

adapters/base-adapter.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {
1717
AgentResult,
1818
AgentInfo,
1919
} from '../types/agent-adapter';
20+
import { AdapterNotInitializedError } from '../lib/errors';
2021

2122
export abstract class BaseAdapter implements IAgentAdapter {
2223
abstract readonly name: string;
@@ -135,7 +136,7 @@ export abstract class BaseAdapter implements IAgentAdapter {
135136
*/
136137
protected ensureReady(): void {
137138
if (!this.ready) {
138-
throw new Error(`Adapter "${this.name}" is not initialized. Call initialize() first.`);
139+
throw new AdapterNotInitializedError(this.name);
139140
}
140141
}
141142
}

0 commit comments

Comments
 (0)