network-ai 5.10.1 → 5.11.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.
- package/INTEGRATION_GUIDE.md +2 -2
- package/README.md +5 -3
- package/SKILL.md +3 -3
- package/dist/esm/adapters/a2a-adapter.js +235 -0
- package/dist/esm/adapters/a2a-adapter.js.map +1 -0
- package/dist/esm/adapters/adapter-registry.js +613 -0
- package/dist/esm/adapters/adapter-registry.js.map +1 -0
- package/dist/esm/adapters/agno-adapter.js +140 -0
- package/dist/esm/adapters/agno-adapter.js.map +1 -0
- package/dist/esm/adapters/anthropic-computer-use-adapter.js +180 -0
- package/dist/esm/adapters/anthropic-computer-use-adapter.js.map +1 -0
- package/dist/esm/adapters/aps-adapter.js +289 -0
- package/dist/esm/adapters/aps-adapter.js.map +1 -0
- package/dist/esm/adapters/autogen-adapter.js +141 -0
- package/dist/esm/adapters/autogen-adapter.js.map +1 -0
- package/dist/esm/adapters/base-adapter.js +104 -0
- package/dist/esm/adapters/base-adapter.js.map +1 -0
- package/dist/esm/adapters/browser-agent-adapter.js +219 -0
- package/dist/esm/adapters/browser-agent-adapter.js.map +1 -0
- package/dist/esm/adapters/codex-adapter.js +318 -0
- package/dist/esm/adapters/codex-adapter.js.map +1 -0
- package/dist/esm/adapters/copilot-adapter.js +132 -0
- package/dist/esm/adapters/copilot-adapter.js.map +1 -0
- package/dist/esm/adapters/crewai-adapter.js +148 -0
- package/dist/esm/adapters/crewai-adapter.js.map +1 -0
- package/dist/esm/adapters/custom-adapter.js +142 -0
- package/dist/esm/adapters/custom-adapter.js.map +1 -0
- package/dist/esm/adapters/custom-streaming-adapter.js +181 -0
- package/dist/esm/adapters/custom-streaming-adapter.js.map +1 -0
- package/dist/esm/adapters/dspy-adapter.js +127 -0
- package/dist/esm/adapters/dspy-adapter.js.map +1 -0
- package/dist/esm/adapters/haystack-adapter.js +149 -0
- package/dist/esm/adapters/haystack-adapter.js.map +1 -0
- package/dist/esm/adapters/hermes-adapter.js +217 -0
- package/dist/esm/adapters/hermes-adapter.js.map +1 -0
- package/dist/esm/adapters/index.js +109 -0
- package/dist/esm/adapters/index.js.map +1 -0
- package/dist/esm/adapters/langchain-adapter.js +134 -0
- package/dist/esm/adapters/langchain-adapter.js.map +1 -0
- package/dist/esm/adapters/langchain-streaming-adapter.js +161 -0
- package/dist/esm/adapters/langchain-streaming-adapter.js.map +1 -0
- package/dist/esm/adapters/langgraph-adapter.js +119 -0
- package/dist/esm/adapters/langgraph-adapter.js.map +1 -0
- package/dist/esm/adapters/llamaindex-adapter.js +135 -0
- package/dist/esm/adapters/llamaindex-adapter.js.map +1 -0
- package/dist/esm/adapters/mcp-adapter.js +200 -0
- package/dist/esm/adapters/mcp-adapter.js.map +1 -0
- package/dist/esm/adapters/minimax-adapter.js +233 -0
- package/dist/esm/adapters/minimax-adapter.js.map +1 -0
- package/dist/esm/adapters/nemoclaw-adapter.js +465 -0
- package/dist/esm/adapters/nemoclaw-adapter.js.map +1 -0
- package/dist/esm/adapters/openai-agents-adapter.js +118 -0
- package/dist/esm/adapters/openai-agents-adapter.js.map +1 -0
- package/dist/esm/adapters/openai-assistants-adapter.js +130 -0
- package/dist/esm/adapters/openai-assistants-adapter.js.map +1 -0
- package/dist/esm/adapters/openclaw-adapter.js +107 -0
- package/dist/esm/adapters/openclaw-adapter.js.map +1 -0
- package/dist/esm/adapters/orchestrator-adapter.js +218 -0
- package/dist/esm/adapters/orchestrator-adapter.js.map +1 -0
- package/dist/esm/adapters/pydantic-ai-adapter.js +163 -0
- package/dist/esm/adapters/pydantic-ai-adapter.js.map +1 -0
- package/dist/esm/adapters/rlm-adapter.js +167 -0
- package/dist/esm/adapters/rlm-adapter.js.map +1 -0
- package/dist/esm/adapters/semantic-kernel-adapter.js +123 -0
- package/dist/esm/adapters/semantic-kernel-adapter.js.map +1 -0
- package/dist/esm/adapters/streaming-base-adapter.js +74 -0
- package/dist/esm/adapters/streaming-base-adapter.js.map +1 -0
- package/dist/esm/adapters/vertex-ai-adapter.js +166 -0
- package/dist/esm/adapters/vertex-ai-adapter.js.map +1 -0
- package/dist/esm/demo-control-plane.js +147 -0
- package/dist/esm/demo-control-plane.js.map +1 -0
- package/dist/esm/demo-worktree-dashboard.js +131 -0
- package/dist/esm/demo-worktree-dashboard.js.map +1 -0
- package/dist/esm/examples/01-hello-swarm.js +165 -0
- package/dist/esm/examples/01-hello-swarm.js.map +1 -0
- package/dist/esm/examples/02-fsm-pipeline.js +189 -0
- package/dist/esm/examples/02-fsm-pipeline.js.map +1 -0
- package/dist/esm/examples/03-parallel-agents.js +192 -0
- package/dist/esm/examples/03-parallel-agents.js.map +1 -0
- package/dist/esm/examples/05-code-review-swarm.js +1177 -0
- package/dist/esm/examples/05-code-review-swarm.js.map +1 -0
- package/dist/esm/examples/06-ai-pipeline-demo.js +263 -0
- package/dist/esm/examples/06-ai-pipeline-demo.js.map +1 -0
- package/dist/esm/examples/07-full-showcase.js +946 -0
- package/dist/esm/examples/07-full-showcase.js.map +1 -0
- package/dist/esm/examples/08-control-plane-stress-demo.js +186 -0
- package/dist/esm/examples/08-control-plane-stress-demo.js.map +1 -0
- package/dist/esm/examples/09-real-langchain.js +231 -0
- package/dist/esm/examples/09-real-langchain.js.map +1 -0
- package/dist/esm/examples/10-nemoclaw-sandbox-swarm.js +270 -0
- package/dist/esm/examples/10-nemoclaw-sandbox-swarm.js.map +1 -0
- package/dist/esm/examples/demo-runner.js +119 -0
- package/dist/esm/examples/demo-runner.js.map +1 -0
- package/dist/esm/index.js +1352 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lib/adapter-hooks.js +216 -0
- package/dist/esm/lib/adapter-hooks.js.map +1 -0
- package/dist/esm/lib/adapter-test-harness.js +118 -0
- package/dist/esm/lib/adapter-test-harness.js.map +1 -0
- package/dist/esm/lib/agent-conversation.js +155 -0
- package/dist/esm/lib/agent-conversation.js.map +1 -0
- package/dist/esm/lib/agent-debate.js +146 -0
- package/dist/esm/lib/agent-debate.js.map +1 -0
- package/dist/esm/lib/agent-memory.js +336 -0
- package/dist/esm/lib/agent-memory.js.map +1 -0
- package/dist/esm/lib/agent-runtime.js +818 -0
- package/dist/esm/lib/agent-runtime.js.map +1 -0
- package/dist/esm/lib/agent-vcr.js +218 -0
- package/dist/esm/lib/agent-vcr.js.map +1 -0
- package/dist/esm/lib/anomaly-detector.js +178 -0
- package/dist/esm/lib/anomaly-detector.js.map +1 -0
- package/dist/esm/lib/approval-inbox.js +385 -0
- package/dist/esm/lib/approval-inbox.js.map +1 -0
- package/dist/esm/lib/auth-guardian.js +692 -0
- package/dist/esm/lib/auth-guardian.js.map +1 -0
- package/dist/esm/lib/auth-validator.js +32 -0
- package/dist/esm/lib/auth-validator.js.map +1 -0
- package/dist/esm/lib/blackboard-backend-crdt.js +251 -0
- package/dist/esm/lib/blackboard-backend-crdt.js.map +1 -0
- package/dist/esm/lib/blackboard-backend-redis.js +244 -0
- package/dist/esm/lib/blackboard-backend-redis.js.map +1 -0
- package/dist/esm/lib/blackboard-backend.js +141 -0
- package/dist/esm/lib/blackboard-backend.js.map +1 -0
- package/dist/esm/lib/blackboard-validator.js +985 -0
- package/dist/esm/lib/blackboard-validator.js.map +1 -0
- package/dist/esm/lib/circuit-breaker.js +164 -0
- package/dist/esm/lib/circuit-breaker.js.map +1 -0
- package/dist/esm/lib/claim-verifier.js +173 -0
- package/dist/esm/lib/claim-verifier.js.map +1 -0
- package/dist/esm/lib/comparison-runner.js +138 -0
- package/dist/esm/lib/comparison-runner.js.map +1 -0
- package/dist/esm/lib/compliance-monitor.js +261 -0
- package/dist/esm/lib/compliance-monitor.js.map +1 -0
- package/dist/esm/lib/confidence-filter.js +210 -0
- package/dist/esm/lib/confidence-filter.js.map +1 -0
- package/dist/esm/lib/config-watcher.js +215 -0
- package/dist/esm/lib/config-watcher.js.map +1 -0
- package/dist/esm/lib/consistency.js +274 -0
- package/dist/esm/lib/consistency.js.map +1 -0
- package/dist/esm/lib/console-ui.js +276 -0
- package/dist/esm/lib/console-ui.js.map +1 -0
- package/dist/esm/lib/context-throttler.js +171 -0
- package/dist/esm/lib/context-throttler.js.map +1 -0
- package/dist/esm/lib/control-plane.js +527 -0
- package/dist/esm/lib/control-plane.js.map +1 -0
- package/dist/esm/lib/cost-governor.js +128 -0
- package/dist/esm/lib/cost-governor.js.map +1 -0
- package/dist/esm/lib/cost-heatmap.js +161 -0
- package/dist/esm/lib/cost-heatmap.js.map +1 -0
- package/dist/esm/lib/coverage-gate.js +213 -0
- package/dist/esm/lib/coverage-gate.js.map +1 -0
- package/dist/esm/lib/coverage-reporter.js +177 -0
- package/dist/esm/lib/coverage-reporter.js.map +1 -0
- package/dist/esm/lib/crdt.js +141 -0
- package/dist/esm/lib/crdt.js.map +1 -0
- package/dist/esm/lib/dashboard-server.js +403 -0
- package/dist/esm/lib/dashboard-server.js.map +1 -0
- package/dist/esm/lib/dry-run.js +130 -0
- package/dist/esm/lib/dry-run.js.map +1 -0
- package/dist/esm/lib/env-manager.js +518 -0
- package/dist/esm/lib/env-manager.js.map +1 -0
- package/dist/esm/lib/errors.js +201 -0
- package/dist/esm/lib/errors.js.map +1 -0
- package/dist/esm/lib/event-bus.js +229 -0
- package/dist/esm/lib/event-bus.js.map +1 -0
- package/dist/esm/lib/explainability.js +102 -0
- package/dist/esm/lib/explainability.js.map +1 -0
- package/dist/esm/lib/fan-out.js +237 -0
- package/dist/esm/lib/fan-out.js.map +1 -0
- package/dist/esm/lib/federated-budget.js +322 -0
- package/dist/esm/lib/federated-budget.js.map +1 -0
- package/dist/esm/lib/fsm-journey.js +478 -0
- package/dist/esm/lib/fsm-journey.js.map +1 -0
- package/dist/esm/lib/goal-decomposer.js +698 -0
- package/dist/esm/lib/goal-decomposer.js.map +1 -0
- package/dist/esm/lib/goal-dsl.js +391 -0
- package/dist/esm/lib/goal-dsl.js.map +1 -0
- package/dist/esm/lib/job-queue.js +310 -0
- package/dist/esm/lib/job-queue.js.map +1 -0
- package/dist/esm/lib/landscape-agent.js +134 -0
- package/dist/esm/lib/landscape-agent.js.map +1 -0
- package/dist/esm/lib/learning-loop.js +181 -0
- package/dist/esm/lib/learning-loop.js.map +1 -0
- package/dist/esm/lib/lifecycle-hooks.js +148 -0
- package/dist/esm/lib/lifecycle-hooks.js.map +1 -0
- package/dist/esm/lib/locked-blackboard.js +1295 -0
- package/dist/esm/lib/locked-blackboard.js.map +1 -0
- package/dist/esm/lib/logger.js +150 -0
- package/dist/esm/lib/logger.js.map +1 -0
- package/dist/esm/lib/mcp-blackboard-tools.js +298 -0
- package/dist/esm/lib/mcp-blackboard-tools.js.map +1 -0
- package/dist/esm/lib/mcp-bridge.js +357 -0
- package/dist/esm/lib/mcp-bridge.js.map +1 -0
- package/dist/esm/lib/mcp-tool-consumer.js +287 -0
- package/dist/esm/lib/mcp-tool-consumer.js.map +1 -0
- package/dist/esm/lib/mcp-tools-control.js +392 -0
- package/dist/esm/lib/mcp-tools-control.js.map +1 -0
- package/dist/esm/lib/mcp-tools-extended.js +371 -0
- package/dist/esm/lib/mcp-tools-extended.js.map +1 -0
- package/dist/esm/lib/mcp-transport-http.js +528 -0
- package/dist/esm/lib/mcp-transport-http.js.map +1 -0
- package/dist/esm/lib/mcp-transport-sse.js +503 -0
- package/dist/esm/lib/mcp-transport-sse.js.map +1 -0
- package/dist/esm/lib/metrics.js +284 -0
- package/dist/esm/lib/metrics.js.map +1 -0
- package/dist/esm/lib/orchestrator-types.js +66 -0
- package/dist/esm/lib/orchestrator-types.js.map +1 -0
- package/dist/esm/lib/otel-bridge.js +167 -0
- package/dist/esm/lib/otel-bridge.js.map +1 -0
- package/dist/esm/lib/partition-planner.js +246 -0
- package/dist/esm/lib/partition-planner.js.map +1 -0
- package/dist/esm/lib/phase-pipeline.js +367 -0
- package/dist/esm/lib/phase-pipeline.js.map +1 -0
- package/dist/esm/lib/playground.js +224 -0
- package/dist/esm/lib/playground.js.map +1 -0
- package/dist/esm/lib/qa-orchestrator.js +296 -0
- package/dist/esm/lib/qa-orchestrator.js.map +1 -0
- package/dist/esm/lib/quadtree.js +259 -0
- package/dist/esm/lib/quadtree.js.map +1 -0
- package/dist/esm/lib/route-classifier.js +217 -0
- package/dist/esm/lib/route-classifier.js.map +1 -0
- package/dist/esm/lib/semantic-search.js +235 -0
- package/dist/esm/lib/semantic-search.js.map +1 -0
- package/dist/esm/lib/shared-blackboard.js +249 -0
- package/dist/esm/lib/shared-blackboard.js.map +1 -0
- package/dist/esm/lib/skill-composer.js +190 -0
- package/dist/esm/lib/skill-composer.js.map +1 -0
- package/dist/esm/lib/speculative-executor.js +107 -0
- package/dist/esm/lib/speculative-executor.js.map +1 -0
- package/dist/esm/lib/strategy-agent.js +626 -0
- package/dist/esm/lib/strategy-agent.js.map +1 -0
- package/dist/esm/lib/swarm-transport.js +307 -0
- package/dist/esm/lib/swarm-transport.js.map +1 -0
- package/dist/esm/lib/swarm-utils.js +510 -0
- package/dist/esm/lib/swarm-utils.js.map +1 -0
- package/dist/esm/lib/task-decomposer.js +272 -0
- package/dist/esm/lib/task-decomposer.js.map +1 -0
- package/dist/esm/lib/telemetry-provider.js +207 -0
- package/dist/esm/lib/telemetry-provider.js.map +1 -0
- package/dist/esm/lib/timeline-scrubber.js +173 -0
- package/dist/esm/lib/timeline-scrubber.js.map +1 -0
- package/dist/esm/lib/topology.js +591 -0
- package/dist/esm/lib/topology.js.map +1 -0
- package/dist/esm/lib/transport-agent.js +366 -0
- package/dist/esm/lib/transport-agent.js.map +1 -0
- package/dist/esm/lib/work-tree-dashboard.js +583 -0
- package/dist/esm/lib/work-tree-dashboard.js.map +1 -0
- package/dist/esm/lib/work-tree-ui.js +333 -0
- package/dist/esm/lib/work-tree-ui.js.map +1 -0
- package/dist/esm/lib/work-tree.js +480 -0
- package/dist/esm/lib/work-tree.js.map +1 -0
- package/dist/esm/run.js +144 -0
- package/dist/esm/run.js.map +1 -0
- package/dist/esm/security.js +1122 -0
- package/dist/esm/security.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/mcp-transport-http.d.ts +203 -0
- package/dist/lib/mcp-transport-http.d.ts.map +1 -0
- package/dist/lib/mcp-transport-http.js +528 -0
- package/dist/lib/mcp-transport-http.js.map +1 -0
- package/dist/lib/phase-pipeline.d.ts +31 -0
- package/dist/lib/phase-pipeline.d.ts.map +1 -1
- package/dist/lib/phase-pipeline.js +93 -1
- package/dist/lib/phase-pipeline.js.map +1 -1
- package/dist/lib/semantic-search.d.ts +42 -6
- package/dist/lib/semantic-search.d.ts.map +1 -1
- package/dist/lib/semantic-search.js +87 -6
- package/dist/lib/semantic-search.js.map +1 -1
- package/package.json +24 -4
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Semantic Memory Search — Embeddings-based retrieval over blackboard data
|
|
4
|
+
*
|
|
5
|
+
* Provides an in-memory vector store that can index blackboard entries and
|
|
6
|
+
* answer similarity queries. Bring your own embedding function (BYOE) —
|
|
7
|
+
* no runtime dependency on any specific model or provider.
|
|
8
|
+
*
|
|
9
|
+
* Optionally persists the index to a JSON file (`persistPath`) so memory
|
|
10
|
+
* survives process restarts without re-embedding everything.
|
|
11
|
+
*
|
|
12
|
+
* Inspired by Claw-Code's semantic memory pattern.
|
|
13
|
+
*
|
|
14
|
+
* @module SemanticSearch
|
|
15
|
+
* @version 1.1.0
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.SemanticMemory = void 0;
|
|
19
|
+
const fs_1 = require("fs");
|
|
20
|
+
const path_1 = require("path");
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// MATH HELPERS
|
|
23
|
+
// ============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* Cosine similarity between two equal-length vectors.
|
|
26
|
+
* Returns 0 for zero-magnitude vectors.
|
|
27
|
+
*/
|
|
28
|
+
function cosineSimilarity(a, b) {
|
|
29
|
+
if (a.length !== b.length || a.length === 0)
|
|
30
|
+
return 0;
|
|
31
|
+
let dot = 0;
|
|
32
|
+
let magA = 0;
|
|
33
|
+
let magB = 0;
|
|
34
|
+
for (let i = 0; i < a.length; i++) {
|
|
35
|
+
dot += a[i] * b[i];
|
|
36
|
+
magA += a[i] * a[i];
|
|
37
|
+
magB += b[i] * b[i];
|
|
38
|
+
}
|
|
39
|
+
const denom = Math.sqrt(magA) * Math.sqrt(magB);
|
|
40
|
+
return denom === 0 ? 0 : dot / denom;
|
|
41
|
+
}
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// SEMANTIC MEMORY
|
|
44
|
+
// ============================================================================
|
|
45
|
+
/**
|
|
46
|
+
* In-memory semantic vector store with optional file-backed persistence.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* // Ephemeral (in-memory only)
|
|
51
|
+
* const memory = new SemanticMemory(async (text) => openai.embed(text));
|
|
52
|
+
*
|
|
53
|
+
* // Persistent across restarts
|
|
54
|
+
* const memory = new SemanticMemory(
|
|
55
|
+
* async (text) => openai.embed(text),
|
|
56
|
+
* { persistPath: './data/semantic-index.json' }
|
|
57
|
+
* );
|
|
58
|
+
* await memory.load(); // restore from disk on startup
|
|
59
|
+
*
|
|
60
|
+
* // Index entries
|
|
61
|
+
* await memory.index('task:1', 'Quarterly revenue analysis', { status: 'done' }, 'analyst');
|
|
62
|
+
* await memory.save(); // flush to disk
|
|
63
|
+
*
|
|
64
|
+
* // Search
|
|
65
|
+
* const results = await memory.search('financial trends', 5);
|
|
66
|
+
* // → [{ key: 'task:1', score: 0.87, ... }]
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
class SemanticMemory {
|
|
70
|
+
entries = new Map();
|
|
71
|
+
embeddingFn;
|
|
72
|
+
persistPath;
|
|
73
|
+
/**
|
|
74
|
+
* @param embeddingFn Function that produces embeddings from text
|
|
75
|
+
* @param options Optional configuration
|
|
76
|
+
* @param options.persistPath Path to a JSON file for durable storage.
|
|
77
|
+
* Call `load()` after construction to restore, and `save()` (or use
|
|
78
|
+
* `autoSave`) to flush writes.
|
|
79
|
+
*/
|
|
80
|
+
constructor(embeddingFn, options) {
|
|
81
|
+
this.embeddingFn = embeddingFn;
|
|
82
|
+
this.persistPath = options?.persistPath ? (0, path_1.resolve)(options.persistPath) : undefined;
|
|
83
|
+
}
|
|
84
|
+
// --------------------------------------------------------------------------
|
|
85
|
+
// Persistence
|
|
86
|
+
// --------------------------------------------------------------------------
|
|
87
|
+
/**
|
|
88
|
+
* Persist the current in-memory index to `persistPath`.
|
|
89
|
+
* No-op when `persistPath` was not set.
|
|
90
|
+
*/
|
|
91
|
+
save() {
|
|
92
|
+
if (!this.persistPath)
|
|
93
|
+
return;
|
|
94
|
+
try {
|
|
95
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(this.persistPath), { recursive: true });
|
|
96
|
+
const data = {
|
|
97
|
+
version: 1,
|
|
98
|
+
savedAt: new Date().toISOString(),
|
|
99
|
+
entries: Array.from(this.entries.values()),
|
|
100
|
+
};
|
|
101
|
+
(0, fs_1.writeFileSync)(this.persistPath, JSON.stringify(data), 'utf-8');
|
|
102
|
+
}
|
|
103
|
+
catch { /* non-fatal */ }
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Restore the index from `persistPath`.
|
|
107
|
+
* No-op when `persistPath` was not set or the file does not exist.
|
|
108
|
+
*
|
|
109
|
+
* Call this once after construction to warm the index from a previous run.
|
|
110
|
+
*/
|
|
111
|
+
load() {
|
|
112
|
+
if (!this.persistPath || !(0, fs_1.existsSync)(this.persistPath))
|
|
113
|
+
return;
|
|
114
|
+
try {
|
|
115
|
+
const raw = (0, fs_1.readFileSync)(this.persistPath, 'utf-8');
|
|
116
|
+
const data = JSON.parse(raw);
|
|
117
|
+
if (data.version !== 1 || !Array.isArray(data.entries))
|
|
118
|
+
return;
|
|
119
|
+
this.entries.clear();
|
|
120
|
+
for (const entry of data.entries) {
|
|
121
|
+
if (typeof entry.key === 'string' &&
|
|
122
|
+
Array.isArray(entry.embedding) &&
|
|
123
|
+
entry.embedding.length > 0) {
|
|
124
|
+
this.entries.set(entry.key, entry);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch { /* non-fatal — start with empty index */ }
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Delete the persistence file.
|
|
132
|
+
* Useful for clearing stale indexes between projects.
|
|
133
|
+
*/
|
|
134
|
+
clearPersisted() {
|
|
135
|
+
if (!this.persistPath || !(0, fs_1.existsSync)(this.persistPath))
|
|
136
|
+
return;
|
|
137
|
+
try {
|
|
138
|
+
const { unlinkSync } = require('fs');
|
|
139
|
+
unlinkSync(this.persistPath);
|
|
140
|
+
}
|
|
141
|
+
catch { /* ignore */ }
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Index a key–value pair with its text representation.
|
|
145
|
+
* Re-indexing the same key replaces the previous embedding.
|
|
146
|
+
*
|
|
147
|
+
* @param key Unique identifier
|
|
148
|
+
* @param text The text to embed for similarity matching
|
|
149
|
+
* @param value The value to return in search results
|
|
150
|
+
* @param sourceAgent Agent that produced this entry
|
|
151
|
+
* @param autoSave Flush to disk after indexing (requires `persistPath`). Default false.
|
|
152
|
+
*/
|
|
153
|
+
async index(key, text, value, sourceAgent, autoSave = false) {
|
|
154
|
+
const embedding = await this.embeddingFn(text);
|
|
155
|
+
this.entries.set(key, { key, text, value, sourceAgent, embedding });
|
|
156
|
+
if (autoSave)
|
|
157
|
+
this.save();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Search for entries similar to the query text.
|
|
161
|
+
*
|
|
162
|
+
* @param query Natural language query
|
|
163
|
+
* @param topK Maximum results to return (default 5)
|
|
164
|
+
* @param threshold Minimum cosine similarity (default 0)
|
|
165
|
+
* @returns Sorted results, highest similarity first
|
|
166
|
+
*/
|
|
167
|
+
async search(query, topK = 5, threshold = 0) {
|
|
168
|
+
if (this.entries.size === 0)
|
|
169
|
+
return [];
|
|
170
|
+
const queryEmbedding = await this.embeddingFn(query);
|
|
171
|
+
const scored = [];
|
|
172
|
+
for (const entry of this.entries.values()) {
|
|
173
|
+
const score = cosineSimilarity(queryEmbedding, entry.embedding);
|
|
174
|
+
if (score >= threshold) {
|
|
175
|
+
scored.push({
|
|
176
|
+
key: entry.key,
|
|
177
|
+
value: entry.value,
|
|
178
|
+
score,
|
|
179
|
+
sourceAgent: entry.sourceAgent,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Sort descending by score, take top-K
|
|
184
|
+
scored.sort((a, b) => b.score - a.score);
|
|
185
|
+
return scored.slice(0, topK);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Bulk-index all entries from a blackboard snapshot.
|
|
189
|
+
*
|
|
190
|
+
* @param snapshot Record of key → { value, source_agent } (from LockedBlackboard.getSnapshot())
|
|
191
|
+
* @returns Number of entries indexed
|
|
192
|
+
*/
|
|
193
|
+
async indexSnapshot(snapshot) {
|
|
194
|
+
let count = 0;
|
|
195
|
+
for (const [key, entry] of Object.entries(snapshot)) {
|
|
196
|
+
const text = typeof entry.value === 'string' ? entry.value : JSON.stringify(entry.value);
|
|
197
|
+
await this.index(key, text, entry.value, entry.source_agent);
|
|
198
|
+
count++;
|
|
199
|
+
}
|
|
200
|
+
return count;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Remove an entry by key.
|
|
204
|
+
* @returns true if an entry was removed
|
|
205
|
+
*/
|
|
206
|
+
remove(key) {
|
|
207
|
+
return this.entries.delete(key);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Remove all indexed entries.
|
|
211
|
+
*/
|
|
212
|
+
clear() {
|
|
213
|
+
this.entries.clear();
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Number of indexed entries.
|
|
217
|
+
*/
|
|
218
|
+
size() {
|
|
219
|
+
return this.entries.size;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Check if a key is indexed.
|
|
223
|
+
*/
|
|
224
|
+
has(key) {
|
|
225
|
+
return this.entries.has(key);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* List all indexed keys.
|
|
229
|
+
*/
|
|
230
|
+
keys() {
|
|
231
|
+
return Array.from(this.entries.keys());
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
exports.SemanticMemory = SemanticMemory;
|
|
235
|
+
//# sourceMappingURL=semantic-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic-search.js","sourceRoot":"","sources":["../../../lib/semantic-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Namespace-scoped, identity-verified shared state for multi-agent coordination.
|
|
4
|
+
*
|
|
5
|
+
* Every write is identity-verified (agent token), namespace-checked,
|
|
6
|
+
* size-validated, input-sanitized, and atomically persisted through
|
|
7
|
+
* the pluggable {@link BlackboardBackend}.
|
|
8
|
+
*
|
|
9
|
+
* @module SharedBlackboard
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SharedBlackboard = void 0;
|
|
13
|
+
const blackboard_backend_1 = require("./blackboard-backend");
|
|
14
|
+
const security_1 = require("../security");
|
|
15
|
+
const errors_1 = require("./errors");
|
|
16
|
+
const orchestrator_types_1 = require("./orchestrator-types");
|
|
17
|
+
/**
|
|
18
|
+
* Namespace-scoped, identity-verified shared state for multi-agent coordination.
|
|
19
|
+
*
|
|
20
|
+
* Every write is identity-verified (agent token), namespace-checked,
|
|
21
|
+
* size-validated, input-sanitized, and atomically persisted through
|
|
22
|
+
* {@link LockedBlackboard}.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const bb = new SharedBlackboard('./workspace');
|
|
27
|
+
* bb.registerAgent('analyst', 'secret-token', ['task:', 'analytics:']);
|
|
28
|
+
* bb.write('task:revenue', { q4: 42_000 }, 'analyst', 3600, 'secret-token');
|
|
29
|
+
* const entry = bb.read('task:revenue');
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
class SharedBlackboard {
|
|
33
|
+
backend;
|
|
34
|
+
agentTokens = new Map(); // agentId -> verified token
|
|
35
|
+
agentNamespaces = new Map(); // agentId -> allowed prefixes
|
|
36
|
+
piiRedactor = null;
|
|
37
|
+
constructor(backendOrPath, options) {
|
|
38
|
+
if (typeof backendOrPath === 'string') {
|
|
39
|
+
if (!backendOrPath || backendOrPath.trim() === '') {
|
|
40
|
+
throw new errors_1.ValidationError('basePath must be a non-empty string');
|
|
41
|
+
}
|
|
42
|
+
this.backend = new blackboard_backend_1.FileBackend(backendOrPath);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
if (!backendOrPath || typeof backendOrPath !== 'object') {
|
|
46
|
+
throw new errors_1.ValidationError('backend must be a BlackboardBackend instance');
|
|
47
|
+
}
|
|
48
|
+
this.backend = backendOrPath;
|
|
49
|
+
}
|
|
50
|
+
if (options?.enablePIIRedaction) {
|
|
51
|
+
this.piiRedactor = new security_1.PIIRedactor();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Enable or disable PII redaction on writes.
|
|
56
|
+
*/
|
|
57
|
+
setPIIRedaction(enabled) {
|
|
58
|
+
this.piiRedactor = enabled ? new security_1.PIIRedactor() : null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Register a verified agent identity. Only agents with registered tokens
|
|
62
|
+
* can write to the blackboard. The orchestrator registers agents after
|
|
63
|
+
* verifying their identity through the AuthGuardian.
|
|
64
|
+
*/
|
|
65
|
+
registerAgent(agentId, verificationToken, allowedNamespaces = ['*']) {
|
|
66
|
+
if (!agentId || typeof agentId !== 'string' || agentId.trim() === '') {
|
|
67
|
+
throw new errors_1.ValidationError('agentId must be a non-empty string');
|
|
68
|
+
}
|
|
69
|
+
if (!verificationToken || typeof verificationToken !== 'string') {
|
|
70
|
+
throw new errors_1.ValidationError('verificationToken must be a non-empty string');
|
|
71
|
+
}
|
|
72
|
+
if (!Array.isArray(allowedNamespaces)) {
|
|
73
|
+
throw new errors_1.ValidationError('allowedNamespaces must be an array of strings');
|
|
74
|
+
}
|
|
75
|
+
this.agentTokens.set(agentId, verificationToken);
|
|
76
|
+
this.agentNamespaces.set(agentId, allowedNamespaces);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if an agent is allowed to access a key based on namespace rules.
|
|
80
|
+
*/
|
|
81
|
+
canAccessKey(agentId, key) {
|
|
82
|
+
const namespaces = this.agentNamespaces.get(agentId);
|
|
83
|
+
if (!namespaces)
|
|
84
|
+
return false;
|
|
85
|
+
if (namespaces.includes('*'))
|
|
86
|
+
return true;
|
|
87
|
+
return namespaces.some(ns => key.startsWith(ns));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Verify that the calling agent is who they claim to be.
|
|
91
|
+
*/
|
|
92
|
+
verifyAgent(agentId, token) {
|
|
93
|
+
const registeredToken = this.agentTokens.get(agentId);
|
|
94
|
+
// If no token system is configured for this agent, allow (backward compat)
|
|
95
|
+
if (!registeredToken)
|
|
96
|
+
return true;
|
|
97
|
+
return token === registeredToken;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Validate value size and structure before writing.
|
|
101
|
+
* Prevents DoS via oversized writes and circular data.
|
|
102
|
+
*/
|
|
103
|
+
validateValue(value) {
|
|
104
|
+
try {
|
|
105
|
+
const serialized = JSON.stringify(value);
|
|
106
|
+
if (serialized.length > orchestrator_types_1.CONFIG.maxBlackboardValueSize) {
|
|
107
|
+
return { valid: false, reason: `Value exceeds max size (${serialized.length} > ${orchestrator_types_1.CONFIG.maxBlackboardValueSize} bytes)` };
|
|
108
|
+
}
|
|
109
|
+
return { valid: true };
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return { valid: false, reason: 'Value cannot be serialized (circular reference or invalid structure)' };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Sanitize a key to prevent markdown injection.
|
|
117
|
+
*/
|
|
118
|
+
sanitizeKey(key) {
|
|
119
|
+
// Keys must be safe for markdown headings -- no #, newlines, or markdown syntax
|
|
120
|
+
return key.replace(/[#\n\r|`]/g, '_').slice(0, 256);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Read an entry from the blackboard by key.
|
|
124
|
+
*
|
|
125
|
+
* @param key - The entry key to look up
|
|
126
|
+
* @returns The entry, or `null` if not found or expired
|
|
127
|
+
* @throws {@link ValidationError} if `key` is not a non-empty string
|
|
128
|
+
*/
|
|
129
|
+
read(key) {
|
|
130
|
+
if (!key || typeof key !== 'string') {
|
|
131
|
+
throw new errors_1.ValidationError('key must be a non-empty string');
|
|
132
|
+
}
|
|
133
|
+
const entry = this.backend.read(key);
|
|
134
|
+
if (!entry)
|
|
135
|
+
return null;
|
|
136
|
+
// Normalize field name for backward compatibility
|
|
137
|
+
return {
|
|
138
|
+
key: entry.key,
|
|
139
|
+
value: entry.value,
|
|
140
|
+
sourceAgent: entry.source_agent ?? entry.sourceAgent ?? 'unknown',
|
|
141
|
+
timestamp: entry.timestamp,
|
|
142
|
+
ttl: entry.ttl,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Write to the blackboard with identity verification, namespace checks,
|
|
147
|
+
* value validation, and input sanitization. Uses LockedBlackboard for
|
|
148
|
+
* atomic file-system writes.
|
|
149
|
+
*
|
|
150
|
+
* @param key - The key to write
|
|
151
|
+
* @param value - The value (will be sanitized and size-checked)
|
|
152
|
+
* @param sourceAgent - Agent claiming to write (verified against registered token)
|
|
153
|
+
* @param ttl - Optional TTL in seconds
|
|
154
|
+
* @param agentToken - Optional verification token for identity check
|
|
155
|
+
*/
|
|
156
|
+
write(key, value, sourceAgent, ttl, agentToken) {
|
|
157
|
+
// 1. Verify agent identity
|
|
158
|
+
if (!this.verifyAgent(sourceAgent, agentToken)) {
|
|
159
|
+
throw new errors_1.IdentityVerificationError(sourceAgent);
|
|
160
|
+
}
|
|
161
|
+
// 2. Namespace check
|
|
162
|
+
if (!this.canAccessKey(sourceAgent, key)) {
|
|
163
|
+
throw new errors_1.NamespaceViolationError(sourceAgent, key);
|
|
164
|
+
}
|
|
165
|
+
// 3. Sanitize key
|
|
166
|
+
const safeKey = this.sanitizeKey(key);
|
|
167
|
+
// 4. Validate value size/structure
|
|
168
|
+
const validation = this.validateValue(value);
|
|
169
|
+
if (!validation.valid) {
|
|
170
|
+
throw new errors_1.ValidationError(validation.reason);
|
|
171
|
+
}
|
|
172
|
+
// 5. Sanitize value -- strip injection payloads from string content
|
|
173
|
+
let sanitizedValue;
|
|
174
|
+
try {
|
|
175
|
+
sanitizedValue = security_1.InputSanitizer.sanitizeObject(value);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
sanitizedValue = value; // Fall back to raw if sanitization can't handle it
|
|
179
|
+
}
|
|
180
|
+
// 5b. PII redaction -- strip emails, SSNs, credit cards, phones, IPs
|
|
181
|
+
if (this.piiRedactor) {
|
|
182
|
+
const { redacted } = this.piiRedactor.redactObject(sanitizedValue);
|
|
183
|
+
sanitizedValue = redacted;
|
|
184
|
+
}
|
|
185
|
+
// 6. Write through backend (atomic when using FileBackend; in-memory for MemoryBackend)
|
|
186
|
+
const entry = this.backend.write(safeKey, sanitizedValue, sourceAgent, ttl);
|
|
187
|
+
// Normalize for backward compat
|
|
188
|
+
return {
|
|
189
|
+
key: entry.key,
|
|
190
|
+
value: entry.value,
|
|
191
|
+
sourceAgent: entry.source_agent ?? sourceAgent,
|
|
192
|
+
timestamp: entry.timestamp,
|
|
193
|
+
ttl: entry.ttl,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Check whether a key exists on the blackboard (not expired).
|
|
198
|
+
* @param key - The entry key to check
|
|
199
|
+
*/
|
|
200
|
+
exists(key) {
|
|
201
|
+
return this.read(key) !== null;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get a full snapshot of all blackboard entries.
|
|
205
|
+
*/
|
|
206
|
+
getSnapshot() {
|
|
207
|
+
const raw = this.backend.getSnapshot();
|
|
208
|
+
const normalized = {};
|
|
209
|
+
for (const [key, entry] of Object.entries(raw)) {
|
|
210
|
+
normalized[key] = {
|
|
211
|
+
key: entry.key,
|
|
212
|
+
value: entry.value,
|
|
213
|
+
sourceAgent: entry.source_agent ?? entry.sourceAgent ?? 'unknown',
|
|
214
|
+
timestamp: entry.timestamp,
|
|
215
|
+
ttl: entry.ttl,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return normalized;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Get a namespace-scoped snapshot -- only returns keys an agent is allowed to see.
|
|
222
|
+
* Prevents data leakage between agents.
|
|
223
|
+
*/
|
|
224
|
+
getScopedSnapshot(agentId) {
|
|
225
|
+
if (!agentId || typeof agentId !== 'string') {
|
|
226
|
+
throw new errors_1.ValidationError('agentId must be a non-empty string');
|
|
227
|
+
}
|
|
228
|
+
const full = this.getSnapshot();
|
|
229
|
+
const scoped = {};
|
|
230
|
+
for (const [key, entry] of Object.entries(full)) {
|
|
231
|
+
if (this.canAccessKey(agentId, key)) {
|
|
232
|
+
scoped[key] = entry;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return scoped;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Clear all entries (for testing).
|
|
239
|
+
*/
|
|
240
|
+
clear() {
|
|
241
|
+
// Write an empty state through locked backend
|
|
242
|
+
const keys = this.backend.listKeys();
|
|
243
|
+
for (const key of keys) {
|
|
244
|
+
this.backend.delete(key);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
exports.SharedBlackboard = SharedBlackboard;
|
|
249
|
+
//# sourceMappingURL=shared-blackboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-blackboard.js","sourceRoot":"","sources":["../../../lib/shared-blackboard.ts"],"names":[],"mappings":"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"}
|