@nxuss/lemma 0.3.3 → 0.4.1

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.
Files changed (59) hide show
  1. package/README.md +42 -330
  2. package/dashboard/README.md +351 -0
  3. package/dashboard/dist/assets/index-CIx8ECj8.css +1 -0
  4. package/dashboard/dist/assets/index-zTlIPJOp.js +478 -0
  5. package/dashboard/dist/assets/index-zTlIPJOp.js.map +1 -0
  6. package/dashboard/dist/index.html +14 -0
  7. package/dist/cjs/api/server.js +1 -1
  8. package/dist/cjs/cli/stack.d.ts +20 -0
  9. package/dist/cjs/cli/stack.d.ts.map +1 -0
  10. package/dist/cjs/cli/stack.js +76 -0
  11. package/dist/cjs/cli/stack.js.map +1 -0
  12. package/dist/cjs/cloud/TenantCache.d.ts +1 -0
  13. package/dist/cjs/cloud/TenantCache.d.ts.map +1 -1
  14. package/dist/cjs/cloud/TenantCache.js +25 -3
  15. package/dist/cjs/cloud/TenantCache.js.map +1 -1
  16. package/dist/cjs/config/index.d.ts.map +1 -1
  17. package/dist/cjs/config/index.js +4 -0
  18. package/dist/cjs/config/index.js.map +1 -1
  19. package/dist/cjs/index.d.ts +3 -1
  20. package/dist/cjs/index.d.ts.map +1 -1
  21. package/dist/cjs/index.js +29 -0
  22. package/dist/cjs/index.js.map +1 -1
  23. package/dist/cjs/observability/IdeContextSync.d.ts +39 -0
  24. package/dist/cjs/observability/IdeContextSync.d.ts.map +1 -0
  25. package/dist/cjs/observability/IdeContextSync.js +169 -0
  26. package/dist/cjs/observability/IdeContextSync.js.map +1 -0
  27. package/dist/cjs/types/index.d.ts +11 -0
  28. package/dist/cjs/types/index.d.ts.map +1 -1
  29. package/dist/cjs/types/index.js.map +1 -1
  30. package/dist/esm/api/server.js +1 -1
  31. package/dist/esm/cli/stack.d.ts +20 -0
  32. package/dist/esm/cli/stack.d.ts.map +1 -0
  33. package/dist/esm/cli/stack.js +73 -0
  34. package/dist/esm/cli/stack.js.map +1 -0
  35. package/dist/esm/cloud/TenantCache.d.ts +1 -0
  36. package/dist/esm/cloud/TenantCache.d.ts.map +1 -1
  37. package/dist/esm/cloud/TenantCache.js +25 -3
  38. package/dist/esm/cloud/TenantCache.js.map +1 -1
  39. package/dist/esm/config/index.d.ts.map +1 -1
  40. package/dist/esm/config/index.js +4 -0
  41. package/dist/esm/config/index.js.map +1 -1
  42. package/dist/esm/index.d.ts +3 -1
  43. package/dist/esm/index.d.ts.map +1 -1
  44. package/dist/esm/index.js +29 -0
  45. package/dist/esm/index.js.map +1 -1
  46. package/dist/esm/observability/IdeContextSync.d.ts +39 -0
  47. package/dist/esm/observability/IdeContextSync.d.ts.map +1 -0
  48. package/dist/esm/observability/IdeContextSync.js +162 -0
  49. package/dist/esm/observability/IdeContextSync.js.map +1 -0
  50. package/dist/esm/types/index.d.ts +11 -0
  51. package/dist/esm/types/index.d.ts.map +1 -1
  52. package/dist/esm/types/index.js.map +1 -1
  53. package/lemma-proxy.cjs +177 -25
  54. package/package.json +15 -13
  55. package/src/cloud/CloudSyncClient.js +35 -0
  56. package/src/protocol/README.md +576 -0
  57. package/src/proxy/ComplexityRouter.js +37 -0
  58. package/src/security/SemanticScrubber.js +54 -0
  59. package/src/speculative/worker.js +96 -0
@@ -0,0 +1,576 @@
1
+ # Inter-Agent Protocol (I.A.P.) v1.0.0
2
+
3
+ ## Overview
4
+
5
+ The **Inter-Agent Protocol (I.A.P.)** is a lightweight, WebSocket-based communication standard that enables autonomous AI agents to discover, negotiate, and collaborate seamlessly across different frameworks and platforms.
6
+
7
+ I.A.P. solves the fragmentation problem in multi-agent systems by providing a common language for:
8
+ - **Agent identification and capability broadcasting**
9
+ - **Dynamic task negotiation and bidding**
10
+ - **Stateful context transfer between agents**
11
+ - **Real-time performance monitoring**
12
+
13
+ ## Core Concepts
14
+
15
+ ### 1. Agent Identity
16
+
17
+ Every agent in the network has a unique `AgentId` and advertises its capabilities through a structured handshake process.
18
+
19
+ ```typescript
20
+ interface AgentHandshake {
21
+ agentId: string;
22
+ name: string;
23
+ version: string;
24
+ framework?: string;
25
+ capabilities: AgentCapability[];
26
+ maxConcurrentTasks?: number;
27
+ currentLoad?: number;
28
+ protocolVersion: string;
29
+ }
30
+ ```
31
+
32
+ ### 2. Capabilities
33
+
34
+ Capabilities define what an agent can do. Each capability includes:
35
+ - **Type**: Predefined category (text generation, code execution, etc.)
36
+ - **Input/Output schemas**: JSON Schema definitions
37
+ - **Performance metrics**: Estimated cost and latency
38
+
39
+ ```typescript
40
+ interface AgentCapability {
41
+ id: string;
42
+ type: CapabilityType;
43
+ name: string;
44
+ description: string;
45
+ inputSchema?: Record<string, any>;
46
+ outputSchema?: Record<string, any>;
47
+ estimatedCost?: number;
48
+ averageLatency?: number;
49
+ }
50
+ ```
51
+
52
+ ### 3. Task Negotiation
53
+
54
+ Tasks flow through a bidding process:
55
+ 1. **Proposal**: An agent proposes a task with requirements
56
+ 2. **Bidding**: Capable agents submit bids with cost/latency estimates
57
+ 3. **Assignment**: Router selects the optimal agent
58
+ 4. **Execution**: Assigned agent executes and returns results
59
+
60
+ ### 4. Context Transfer
61
+
62
+ Agents can pass stateful information without re-summarizing:
63
+
64
+ ```typescript
65
+ interface ContextTransfer {
66
+ fromAgent: AgentId;
67
+ toAgent: AgentId;
68
+ taskId: TaskId;
69
+ contextType: string;
70
+ data: Record<string, any>;
71
+ embedding?: number[]; // For semantic indexing
72
+ compression?: 'gzip' | 'brotli' | 'none';
73
+ }
74
+ ```
75
+
76
+ ## Protocol Flows
77
+
78
+ ### Connection Flow
79
+
80
+ ```mermaid
81
+ sequenceDiagram
82
+ participant Agent
83
+ participant Router
84
+
85
+ Agent->>Router: HANDSHAKE (capabilities)
86
+ Router->>Agent: HANDSHAKE_ACK (session)
87
+ loop Maintain Connection
88
+ Agent->>Router: HEARTBEAT
89
+ end
90
+ Agent->>Router: DISCONNECT
91
+ ```
92
+
93
+ **Steps:**
94
+ 1. Agent sends `HANDSHAKE` with capabilities
95
+ 2. Router responds with `HANDSHAKE_ACK` and session ID
96
+ 3. Agent sends periodic `HEARTBEAT` messages
97
+ 4. Agent sends `DISCONNECT` when leaving
98
+
99
+ ### Discovery Flow
100
+
101
+ ```mermaid
102
+ sequenceDiagram
103
+ participant Agent A
104
+ participant Router
105
+
106
+ Agent A->>Router: CAPABILITY_DISCOVERY
107
+ Router->>Agent A: CAPABILITY_RESPONSE (all agents)
108
+ ```
109
+
110
+ **Steps:**
111
+ 1. Agent sends `CAPABILITY_DISCOVERY` request
112
+ 2. Router responds with all available agents and their capabilities
113
+
114
+ ### Task Negotiation Flow
115
+
116
+ ```mermaid
117
+ sequenceDiagram
118
+ participant Agent A
119
+ participant Router
120
+ participant Agent B
121
+ participant Agent C
122
+
123
+ Agent A->>Router: TASK_PROPOSAL
124
+ Router->>Agent B: TASK_PROPOSAL (broadcast)
125
+ Router->>Agent C: TASK_PROPOSAL (broadcast)
126
+ Agent B->>Router: TASK_BID
127
+ Agent C->>Router: TASK_BID
128
+ Router->>Agent B: TASK_ASSIGNMENT (best bid)
129
+ Agent B->>Router: TASK_ACCEPTANCE
130
+ Agent B->>Router: TASK_RESULT
131
+ Router->>Agent A: TASK_RESULT
132
+ ```
133
+
134
+ **Steps:**
135
+ 1. Agent A proposes a task to the router
136
+ 2. Router broadcasts to all capable agents
137
+ 3. Agents B and C submit bids
138
+ 4. Router assigns to best bidder (Agent B)
139
+ 5. Agent B accepts and executes
140
+ 6. Agent B returns result to router
141
+ 7. Router forwards result to Agent A
142
+
143
+ ### Context Transfer Flow
144
+
145
+ ```mermaid
146
+ sequenceDiagram
147
+ participant Agent A
148
+ participant Router
149
+ participant Agent B
150
+
151
+ Agent A->>Router: CONTEXT_TRANSFER
152
+ Router->>Agent B: CONTEXT_TRANSFER
153
+ ```
154
+
155
+ **Steps:**
156
+ 1. Agent A sends context to router
157
+ 2. Router forwards to Agent B
158
+ 3. Agent B continues execution with transferred state
159
+
160
+ ## Message Types
161
+
162
+ ### Core Messages
163
+
164
+ | Type | Direction | Purpose |
165
+ |------|-----------|---------|
166
+ | `HANDSHAKE` | Agent → Router | Initial connection and capability registration |
167
+ | `HANDSHAKE_ACK` | Router → Agent | Connection acknowledgment |
168
+ | `CAPABILITY_DISCOVERY` | Agent → Router | Query available capabilities |
169
+ | `CAPABILITY_RESPONSE` | Router → Agent | List of agents and capabilities |
170
+ | `TASK_PROPOSAL` | Agent → Router | Propose a task for execution |
171
+ | `TASK_BID` | Agent → Router | Bid on a proposed task |
172
+ | `TASK_ASSIGNMENT` | Router → Agent | Assign task to winning bidder |
173
+ | `TASK_ACCEPTANCE` | Agent → Router | Accept assigned task |
174
+ | `TASK_REJECTION` | Agent → Router | Reject assigned task |
175
+ | `CONTEXT_TRANSFER` | Agent ↔ Agent | Transfer execution context |
176
+ | `TASK_RESULT` | Agent → Router | Return task execution result |
177
+ | `ERROR` | Any → Any | Error notification |
178
+ | `HEARTBEAT` | Agent → Router | Keep-alive signal |
179
+ | `DISCONNECT` | Agent → Router | Graceful disconnect |
180
+
181
+ ## Message Structure
182
+
183
+ All I.A.P. messages follow a common structure:
184
+
185
+ ```typescript
186
+ interface IAPMessage {
187
+ messageId: string; // Unique message identifier
188
+ type: MessageType; // Message type
189
+ from: AgentId; // Sender
190
+ to: AgentId | 'router'; // Recipient
191
+ timestamp: string; // ISO 8601 timestamp
192
+ protocolVersion: string; // Protocol version (1.0.0)
193
+ payload: any; // Type-specific payload
194
+ correlationId?: string; // For request-response tracking
195
+ metadata?: Record<string, any>;
196
+ }
197
+ ```
198
+
199
+ ## Usage Examples
200
+
201
+ ### 1. Agent Registration
202
+
203
+ ```typescript
204
+ import {
205
+ createHandshakeMessage,
206
+ AgentHandshake,
207
+ CapabilityType
208
+ } from './protocol';
209
+
210
+ const handshake: AgentHandshake = {
211
+ agentId: 'agent_langchain_001',
212
+ name: 'LangChain Code Assistant',
213
+ version: '1.0.0',
214
+ framework: 'LangChain',
215
+ protocolVersion: '1.0.0',
216
+ capabilities: [
217
+ {
218
+ id: 'code_gen_python',
219
+ type: CapabilityType.CODE_EXECUTION,
220
+ name: 'Python Code Generation',
221
+ description: 'Generate and execute Python code',
222
+ estimatedCost: 100,
223
+ averageLatency: 2000
224
+ }
225
+ ],
226
+ maxConcurrentTasks: 5,
227
+ currentLoad: 0.2
228
+ };
229
+
230
+ const message = createHandshakeMessage(handshake);
231
+ websocket.send(JSON.stringify(message));
232
+ ```
233
+
234
+ ### 2. Task Proposal
235
+
236
+ ```typescript
237
+ import {
238
+ createTaskProposalMessage,
239
+ TaskProposal,
240
+ CapabilityType,
241
+ generateTaskId
242
+ } from './protocol';
243
+
244
+ const proposal: TaskProposal = {
245
+ taskId: generateTaskId(),
246
+ proposerId: 'agent_main_001',
247
+ description: 'Analyze CSV file and generate summary statistics',
248
+ requiredCapability: CapabilityType.DATA_ANALYSIS,
249
+ input: {
250
+ filePath: '/data/sales.csv',
251
+ operations: ['mean', 'median', 'std']
252
+ },
253
+ maxLatency: 5000,
254
+ maxCost: 200,
255
+ priority: 7
256
+ };
257
+
258
+ const message = createTaskProposalMessage(proposal);
259
+ websocket.send(JSON.stringify(message));
260
+ ```
261
+
262
+ ### 3. Submitting a Bid
263
+
264
+ ```typescript
265
+ import { createTaskBidMessage, TaskBid } from './protocol';
266
+
267
+ const bid: TaskBid = {
268
+ taskId: 'task_abc123',
269
+ bidderId: 'agent_data_001',
270
+ estimatedLatency: 3000,
271
+ estimatedCost: 150,
272
+ confidence: 0.95,
273
+ queueDepth: 2,
274
+ notes: 'Specialized in CSV analysis with pandas'
275
+ };
276
+
277
+ const message = createTaskBidMessage(bid, 'agent_data_001');
278
+ websocket.send(JSON.stringify(message));
279
+ ```
280
+
281
+ ### 4. Context Transfer
282
+
283
+ ```typescript
284
+ import { createContextTransferMessage, ContextTransfer } from './protocol';
285
+
286
+ const transfer: ContextTransfer = {
287
+ fromAgent: 'agent_a',
288
+ toAgent: 'agent_b',
289
+ taskId: 'task_xyz789',
290
+ contextType: 'conversation_history',
291
+ data: {
292
+ messages: [
293
+ { role: 'user', content: 'Hello' },
294
+ { role: 'assistant', content: 'Hi there!' }
295
+ ],
296
+ metadata: { sessionId: 'session_123' }
297
+ },
298
+ compression: 'none'
299
+ };
300
+
301
+ const message = createContextTransferMessage(transfer);
302
+ websocket.send(JSON.stringify(message));
303
+ ```
304
+
305
+ ### 5. Message Validation
306
+
307
+ ```typescript
308
+ import { validateIAPMessage, validateHandshake } from './protocol';
309
+
310
+ // Validate complete message
311
+ const result = validateIAPMessage(incomingMessage);
312
+ if (!result.valid) {
313
+ console.error('Validation errors:', result.errors);
314
+ }
315
+
316
+ // Validate specific payload
317
+ const handshakeResult = validateHandshake(handshakePayload);
318
+ if (!handshakeResult.valid) {
319
+ console.error('Invalid handshake:', handshakeResult.errors);
320
+ }
321
+ ```
322
+
323
+ ## State Management
324
+
325
+ ### Flow States
326
+
327
+ The protocol defines a state machine for tracking agent and task states:
328
+
329
+ ```typescript
330
+ enum FlowState {
331
+ DISCONNECTED = 'disconnected',
332
+ HANDSHAKING = 'handshaking',
333
+ CONNECTED = 'connected',
334
+ IDLE = 'idle',
335
+ DISCOVERING = 'discovering',
336
+ PROPOSING = 'proposing',
337
+ BIDDING = 'bidding',
338
+ ASSIGNING = 'assigning',
339
+ EXECUTING = 'executing',
340
+ TRANSFERRING_CONTEXT = 'transferring_context',
341
+ COMPLETING = 'completing',
342
+ ERROR = 'error',
343
+ DISCONNECTING = 'disconnecting'
344
+ }
345
+ ```
346
+
347
+ ### Task Lifecycle
348
+
349
+ ```typescript
350
+ enum TaskStatus {
351
+ PROPOSED = 'proposed',
352
+ BIDDING = 'bidding',
353
+ ASSIGNED = 'assigned',
354
+ IN_PROGRESS = 'in_progress',
355
+ COMPLETED = 'completed',
356
+ FAILED = 'failed',
357
+ CANCELLED = 'cancelled'
358
+ }
359
+ ```
360
+
361
+ ### State Transitions
362
+
363
+ ```typescript
364
+ import {
365
+ createFlowContext,
366
+ transitionFlow,
367
+ MessageType
368
+ } from './protocol';
369
+
370
+ // Create initial context
371
+ const context = createFlowContext('agent_001');
372
+
373
+ // Transition through states
374
+ const newContext = transitionFlow(context, MessageType.HANDSHAKE);
375
+ // context.currentState: DISCONNECTED -> HANDSHAKING
376
+ ```
377
+
378
+ ## Performance Considerations
379
+
380
+ ### Message Size
381
+
382
+ - Keep payloads under 10KB for optimal performance
383
+ - Use compression for larger context transfers
384
+ - Consider chunking for very large data transfers
385
+
386
+ ### Latency Targets
387
+
388
+ - **Handshake**: < 100ms
389
+ - **Discovery**: < 50ms
390
+ - **Task Assignment**: < 100ms
391
+ - **Context Transfer**: < 200ms (depends on size)
392
+
393
+ ### Heartbeat Interval
394
+
395
+ Recommended: 30 seconds
396
+ - Balances connection monitoring with network overhead
397
+ - Adjust based on network reliability
398
+
399
+ ## Error Handling
400
+
401
+ ### Error Codes
402
+
403
+ | Code | Description | Recoverable |
404
+ |------|-------------|-------------|
405
+ | `VALIDATION_ERROR` | Message validation failed | Yes |
406
+ | `CAPABILITY_NOT_FOUND` | Required capability unavailable | Yes |
407
+ | `TASK_TIMEOUT` | Task execution exceeded deadline | No |
408
+ | `AGENT_OVERLOAD` | Agent at maximum capacity | Yes |
409
+ | `CONTEXT_TRANSFER_FAILED` | Context transfer failed | Yes |
410
+ | `PROTOCOL_VERSION_MISMATCH` | Incompatible protocol versions | No |
411
+
412
+ ### Error Message Example
413
+
414
+ ```typescript
415
+ import { createErrorMessage, ErrorMessage } from './protocol';
416
+
417
+ const error: ErrorMessage = {
418
+ code: 'TASK_TIMEOUT',
419
+ message: 'Task execution exceeded 5000ms deadline',
420
+ relatedTaskId: 'task_abc123',
421
+ details: { actualLatency: 6500 },
422
+ recoverable: false
423
+ };
424
+
425
+ const message = createErrorMessage(
426
+ 'agent_001',
427
+ 'router',
428
+ error,
429
+ 'msg_original_123'
430
+ );
431
+ ```
432
+
433
+ ## Security Considerations
434
+
435
+ ### Authentication
436
+
437
+ - Implement agent authentication at the WebSocket layer
438
+ - Use JWT tokens or API keys for agent identification
439
+ - Validate agent identity during handshake
440
+
441
+ ### Authorization
442
+
443
+ - Enforce capability-based access control
444
+ - Validate task permissions before assignment
445
+ - Audit all agent actions
446
+
447
+ ### Data Protection
448
+
449
+ - Encrypt sensitive data in context transfers
450
+ - Use checksums to verify data integrity
451
+ - Implement rate limiting to prevent abuse
452
+
453
+ ## Integration with Subconscious Router
454
+
455
+ The I.A.P. protocol is designed to work seamlessly with the Subconscious Router's semantic caching:
456
+
457
+ 1. **Semantic Interception**: Router checks incoming tasks against vector database
458
+ 2. **Cache Hit**: Return cached result (< 50ms) without agent execution
459
+ 3. **Cache Miss**: Route to appropriate agent via I.A.P. negotiation
460
+ 4. **Result Caching**: Store result with embedding for future hits
461
+
462
+ ```typescript
463
+ // Pseudo-code for router integration
464
+ async function handleTaskProposal(proposal: TaskProposal) {
465
+ // Check semantic cache
466
+ const cached = await semanticCache.query(proposal.description);
467
+
468
+ if (cached && cached.similarity > 0.95) {
469
+ // Instant response from cache
470
+ return cached.result;
471
+ }
472
+
473
+ // Route via I.A.P. negotiation
474
+ const bids = await broadcastTaskProposal(proposal);
475
+ const winner = selectBestBid(bids);
476
+ const result = await assignAndExecute(winner, proposal);
477
+
478
+ // Cache for future
479
+ await semanticCache.store(proposal.description, result);
480
+
481
+ return result;
482
+ }
483
+ ```
484
+
485
+ ## Framework Integration
486
+
487
+ ### LangChain
488
+
489
+ ```typescript
490
+ import { LangChainAgent } from '@langchain/core';
491
+ import { IAPClient } from './iap-client';
492
+
493
+ const agent = new LangChainAgent(/* config */);
494
+ const iapClient = new IAPClient('ws://router:8080');
495
+
496
+ await iapClient.connect({
497
+ agentId: 'langchain_001',
498
+ name: 'LangChain Agent',
499
+ capabilities: agent.getCapabilities()
500
+ });
501
+ ```
502
+
503
+ ### CrewAI
504
+
505
+ ```python
506
+ from crewai import Agent
507
+ from iap_client import IAPClient
508
+
509
+ agent = Agent(role="researcher", goal="Research topics")
510
+ iap_client = IAPClient("ws://router:8080")
511
+
512
+ await iap_client.connect(
513
+ agent_id="crewai_001",
514
+ name="CrewAI Researcher",
515
+ capabilities=agent.get_capabilities()
516
+ )
517
+ ```
518
+
519
+ ### AutoGPT
520
+
521
+ ```typescript
522
+ import { AutoGPTAgent } from 'autogpt';
523
+ import { IAPClient } from './iap-client';
524
+
525
+ const agent = new AutoGPTAgent(/* config */);
526
+ const iapClient = new IAPClient('ws://router:8080');
527
+
528
+ await iapClient.connect({
529
+ agentId: 'autogpt_001',
530
+ name: 'AutoGPT Agent',
531
+ capabilities: agent.listCapabilities()
532
+ });
533
+ ```
534
+
535
+ ## Versioning
536
+
537
+ The protocol follows semantic versioning (MAJOR.MINOR.PATCH):
538
+
539
+ - **MAJOR**: Breaking changes to message structure or flow
540
+ - **MINOR**: New message types or optional fields
541
+ - **PATCH**: Bug fixes and clarifications
542
+
543
+ Current version: **1.0.0**
544
+
545
+ ### Version Compatibility
546
+
547
+ - Agents must specify `protocolVersion` in handshake
548
+ - Router validates version compatibility (same major version)
549
+ - Incompatible versions receive `PROTOCOL_VERSION_MISMATCH` error
550
+
551
+ ## Future Enhancements
552
+
553
+ ### v1.1.0 (Planned)
554
+ - Message batching for high-throughput scenarios
555
+ - Streaming responses for long-running tasks
556
+ - Agent reputation and trust scoring
557
+
558
+ ### v2.0.0 (Roadmap)
559
+ - Direct agent-to-agent communication (bypass router)
560
+ - Multi-router federation
561
+ - Advanced consensus mechanisms
562
+
563
+ ## Contributing
564
+
565
+ Contributions to the I.A.P. specification are welcome! Please submit issues and pull requests to the [GitHub repository](https://github.com/subconscious-router/iap).
566
+
567
+ ## License
568
+
569
+ MIT License - See LICENSE file for details
570
+
571
+ ## References
572
+
573
+ - [Subconscious Router Technical Specification](../../TECHNICAL_SPEC.md)
574
+ - [WebSocket Protocol (RFC 6455)](https://tools.ietf.org/html/rfc6455)
575
+ - [JSON Schema](https://json-schema.org/)
576
+ - [Semantic Versioning](https://semver.org/)
@@ -0,0 +1,37 @@
1
+ // Complexity Router - Evaluates prompt complexity to optimize LLM cost
2
+ class ComplexityRouter {
3
+ constructor() {
4
+ this.cheapModel = 'gpt-4o-mini';
5
+ this.complexKeywords = ['architecture', 'design', 'debug', 'trace', 'system', 'microservices', 'explain', 'why', 'refactor', 'optimize'];
6
+ }
7
+
8
+ evaluate(prompt, originalModel) {
9
+ if (!prompt || prompt.length < 10) return { model: this.cheapModel, complexity: 'low' };
10
+
11
+ const lower = prompt.toLowerCase();
12
+ let isComplex = false;
13
+
14
+ // Heuristic 1: Prompt Length
15
+ if (prompt.length > 500) {
16
+ isComplex = true;
17
+ }
18
+
19
+ // Heuristic 2: Keywords that imply deep reasoning
20
+ for (const kw of this.complexKeywords) {
21
+ if (lower.includes(kw)) {
22
+ isComplex = true;
23
+ break;
24
+ }
25
+ }
26
+
27
+ if (isComplex) {
28
+ console.log(`[ComplexityRouter] High complexity detected. Routing to ${originalModel}`);
29
+ return { model: originalModel || 'gpt-4o', complexity: 'high' };
30
+ } else {
31
+ console.log(`[ComplexityRouter] Low complexity detected. Routing to ${this.cheapModel}`);
32
+ return { model: this.cheapModel, complexity: 'low' };
33
+ }
34
+ }
35
+ }
36
+
37
+ module.exports = ComplexityRouter;
@@ -0,0 +1,54 @@
1
+ // Privacy Firewall - Semantic Scrubber for PII and Secrets
2
+ class SemanticScrubber {
3
+ constructor() {
4
+ this.patterns = [
5
+ { name: 'API_KEY', regex: /(sk-[a-zA-Z0-9\-]{20,})/g },
6
+ { name: 'EMAIL', regex: /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/g },
7
+ { name: 'TOKEN', regex: /(Bearer\s+[a-zA-Z0-9\-._~+/]+=*)/gi }
8
+ ];
9
+ }
10
+
11
+ mask(prompt) {
12
+ let maskedPrompt = prompt;
13
+ const tokenMap = {};
14
+ let counter = 1;
15
+
16
+ for (const pattern of this.patterns) {
17
+ maskedPrompt = maskedPrompt.replace(pattern.regex, (match) => {
18
+ const token = `[${pattern.name}_${counter++}]`;
19
+ tokenMap[token] = match;
20
+ return token;
21
+ });
22
+ }
23
+
24
+ if (Object.keys(tokenMap).length > 0) {
25
+ console.log(`[PrivacyFirewall] Masked ${Object.keys(tokenMap).length} secrets.`);
26
+ }
27
+
28
+ return { maskedPrompt, tokenMap };
29
+ }
30
+
31
+ unmask(responseObj, tokenMap) {
32
+ if (!responseObj || Object.keys(tokenMap).length === 0) return responseObj;
33
+
34
+ let str = typeof responseObj === 'string' ? responseObj : JSON.stringify(responseObj);
35
+
36
+ for (const [token, value] of Object.entries(tokenMap)) {
37
+ str = str.split(token).join(value);
38
+ }
39
+
40
+ return typeof responseObj === 'string' ? str : JSON.parse(str);
41
+ }
42
+
43
+ // Unmask a single stream chunk string
44
+ unmaskString(str, tokenMap) {
45
+ if (!str || Object.keys(tokenMap).length === 0) return str;
46
+ let unmasked = str;
47
+ for (const [token, value] of Object.entries(tokenMap)) {
48
+ unmasked = unmasked.split(token).join(value);
49
+ }
50
+ return unmasked;
51
+ }
52
+ }
53
+
54
+ module.exports = SemanticScrubber;