network-ai 4.15.3 → 5.0.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 +11 -4
- package/QUICKSTART.md +31 -4
- package/README.md +37 -15
- package/bin/dashboard.ts +146 -0
- package/bin/mcp-server.ts +3 -2
- package/dist/adapters/adapter-registry.d.ts +33 -1
- package/dist/adapters/adapter-registry.d.ts.map +1 -1
- package/dist/adapters/adapter-registry.js +49 -0
- package/dist/adapters/adapter-registry.js.map +1 -1
- package/dist/adapters/anthropic-computer-use-adapter.d.ts +132 -0
- package/dist/adapters/anthropic-computer-use-adapter.d.ts.map +1 -0
- package/dist/adapters/anthropic-computer-use-adapter.js +180 -0
- package/dist/adapters/anthropic-computer-use-adapter.js.map +1 -0
- package/dist/adapters/browser-agent-adapter.d.ts +121 -0
- package/dist/adapters/browser-agent-adapter.d.ts.map +1 -0
- package/dist/adapters/browser-agent-adapter.js +219 -0
- package/dist/adapters/browser-agent-adapter.js.map +1 -0
- package/dist/adapters/copilot-adapter.d.ts +59 -0
- package/dist/adapters/copilot-adapter.d.ts.map +1 -0
- package/dist/adapters/copilot-adapter.js +132 -0
- package/dist/adapters/copilot-adapter.js.map +1 -0
- package/dist/adapters/index.d.ts +15 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +22 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/langgraph-adapter.d.ts +70 -0
- package/dist/adapters/langgraph-adapter.d.ts.map +1 -0
- package/dist/adapters/langgraph-adapter.js +119 -0
- package/dist/adapters/langgraph-adapter.js.map +1 -0
- package/dist/adapters/openai-agents-adapter.d.ts +100 -0
- package/dist/adapters/openai-agents-adapter.d.ts.map +1 -0
- package/dist/adapters/openai-agents-adapter.js +118 -0
- package/dist/adapters/openai-agents-adapter.js.map +1 -0
- package/dist/adapters/pydantic-ai-adapter.d.ts +104 -0
- package/dist/adapters/pydantic-ai-adapter.d.ts.map +1 -0
- package/dist/adapters/pydantic-ai-adapter.js +163 -0
- package/dist/adapters/pydantic-ai-adapter.js.map +1 -0
- package/dist/adapters/vertex-ai-adapter.d.ts +122 -0
- package/dist/adapters/vertex-ai-adapter.d.ts.map +1 -0
- package/dist/adapters/vertex-ai-adapter.js +166 -0
- package/dist/adapters/vertex-ai-adapter.js.map +1 -0
- package/dist/bin/dashboard.d.ts +11 -0
- package/dist/bin/dashboard.d.ts.map +1 -0
- package/dist/bin/dashboard.js +135 -0
- package/dist/bin/dashboard.js.map +1 -0
- package/dist/bin/mcp-server.js +3 -2
- package/dist/bin/mcp-server.js.map +1 -1
- package/dist/index.d.ts +103 -559
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +295 -1074
- package/dist/index.js.map +1 -1
- package/dist/lib/adapter-test-harness.d.ts +88 -0
- package/dist/lib/adapter-test-harness.d.ts.map +1 -0
- package/dist/lib/adapter-test-harness.js +118 -0
- package/dist/lib/adapter-test-harness.js.map +1 -0
- package/dist/lib/agent-conversation.d.ts +115 -0
- package/dist/lib/agent-conversation.d.ts.map +1 -0
- package/dist/lib/agent-conversation.js +155 -0
- package/dist/lib/agent-conversation.js.map +1 -0
- package/dist/lib/agent-debate.d.ts +115 -0
- package/dist/lib/agent-debate.d.ts.map +1 -0
- package/dist/lib/agent-debate.js +146 -0
- package/dist/lib/agent-debate.js.map +1 -0
- package/dist/lib/agent-memory.d.ts +157 -0
- package/dist/lib/agent-memory.d.ts.map +1 -0
- package/dist/lib/agent-memory.js +336 -0
- package/dist/lib/agent-memory.js.map +1 -0
- package/dist/lib/agent-vcr.d.ts +133 -0
- package/dist/lib/agent-vcr.d.ts.map +1 -0
- package/dist/lib/agent-vcr.js +218 -0
- package/dist/lib/agent-vcr.js.map +1 -0
- package/dist/lib/anomaly-detector.d.ts +112 -0
- package/dist/lib/anomaly-detector.d.ts.map +1 -0
- package/dist/lib/anomaly-detector.js +178 -0
- package/dist/lib/anomaly-detector.js.map +1 -0
- package/dist/lib/approval-inbox.d.ts +147 -0
- package/dist/lib/approval-inbox.d.ts.map +1 -0
- package/dist/lib/approval-inbox.js +385 -0
- package/dist/lib/approval-inbox.js.map +1 -0
- package/dist/lib/auth-guardian.d.ts +170 -0
- package/dist/lib/auth-guardian.d.ts.map +1 -0
- package/dist/lib/auth-guardian.js +604 -0
- package/dist/lib/auth-guardian.js.map +1 -0
- package/dist/lib/auth-validator.d.ts +70 -0
- package/dist/lib/auth-validator.d.ts.map +1 -0
- package/dist/lib/auth-validator.js +32 -0
- package/dist/lib/auth-validator.js.map +1 -0
- package/dist/lib/blackboard-validator.d.ts +56 -0
- package/dist/lib/blackboard-validator.d.ts.map +1 -1
- package/dist/lib/blackboard-validator.js +181 -4
- package/dist/lib/blackboard-validator.js.map +1 -1
- package/dist/lib/comparison-runner.d.ts +99 -0
- package/dist/lib/comparison-runner.d.ts.map +1 -0
- package/dist/lib/comparison-runner.js +138 -0
- package/dist/lib/comparison-runner.js.map +1 -0
- package/dist/lib/config-watcher.d.ts +109 -0
- package/dist/lib/config-watcher.d.ts.map +1 -0
- package/dist/lib/config-watcher.js +215 -0
- package/dist/lib/config-watcher.js.map +1 -0
- package/dist/lib/cost-governor.d.ts +105 -0
- package/dist/lib/cost-governor.d.ts.map +1 -0
- package/dist/lib/cost-governor.js +128 -0
- package/dist/lib/cost-governor.js.map +1 -0
- package/dist/lib/cost-heatmap.d.ts +104 -0
- package/dist/lib/cost-heatmap.d.ts.map +1 -0
- package/dist/lib/cost-heatmap.js +161 -0
- package/dist/lib/cost-heatmap.js.map +1 -0
- package/dist/lib/coverage-reporter.d.ts +92 -0
- package/dist/lib/coverage-reporter.d.ts.map +1 -0
- package/dist/lib/coverage-reporter.js +177 -0
- package/dist/lib/coverage-reporter.js.map +1 -0
- package/dist/lib/dashboard-server.d.ts +71 -0
- package/dist/lib/dashboard-server.d.ts.map +1 -0
- package/dist/lib/dashboard-server.js +403 -0
- package/dist/lib/dashboard-server.js.map +1 -0
- package/dist/lib/dry-run.d.ts +73 -0
- package/dist/lib/dry-run.d.ts.map +1 -0
- package/dist/lib/dry-run.js +130 -0
- package/dist/lib/dry-run.js.map +1 -0
- package/dist/lib/errors.d.ts +15 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +38 -0
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/event-bus.d.ts +167 -0
- package/dist/lib/event-bus.d.ts.map +1 -0
- package/dist/lib/event-bus.js +229 -0
- package/dist/lib/event-bus.js.map +1 -0
- package/dist/lib/explainability.d.ts +85 -0
- package/dist/lib/explainability.d.ts.map +1 -0
- package/dist/lib/explainability.js +102 -0
- package/dist/lib/explainability.js.map +1 -0
- package/dist/lib/goal-dsl.d.ts +157 -0
- package/dist/lib/goal-dsl.d.ts.map +1 -0
- package/dist/lib/goal-dsl.js +392 -0
- package/dist/lib/goal-dsl.js.map +1 -0
- package/dist/lib/job-queue.d.ts +183 -0
- package/dist/lib/job-queue.d.ts.map +1 -0
- package/dist/lib/job-queue.js +310 -0
- package/dist/lib/job-queue.js.map +1 -0
- package/dist/lib/learning-loop.d.ts +113 -0
- package/dist/lib/learning-loop.d.ts.map +1 -0
- package/dist/lib/learning-loop.js +181 -0
- package/dist/lib/learning-loop.js.map +1 -0
- package/dist/lib/lifecycle-hooks.d.ts +116 -0
- package/dist/lib/lifecycle-hooks.d.ts.map +1 -0
- package/dist/lib/lifecycle-hooks.js +148 -0
- package/dist/lib/lifecycle-hooks.js.map +1 -0
- package/dist/lib/locked-blackboard.d.ts.map +1 -1
- package/dist/lib/locked-blackboard.js +9 -5
- package/dist/lib/locked-blackboard.js.map +1 -1
- package/dist/lib/mcp-tool-consumer.d.ts +153 -0
- package/dist/lib/mcp-tool-consumer.d.ts.map +1 -0
- package/dist/lib/mcp-tool-consumer.js +320 -0
- package/dist/lib/mcp-tool-consumer.js.map +1 -0
- package/dist/lib/metrics.d.ts +119 -0
- package/dist/lib/metrics.d.ts.map +1 -0
- package/dist/lib/metrics.js +284 -0
- package/dist/lib/metrics.js.map +1 -0
- package/dist/lib/orchestrator-types.d.ts +309 -0
- package/dist/lib/orchestrator-types.d.ts.map +1 -0
- package/dist/lib/orchestrator-types.js +61 -0
- package/dist/lib/orchestrator-types.js.map +1 -0
- package/dist/lib/otel-bridge.d.ts +74 -0
- package/dist/lib/otel-bridge.d.ts.map +1 -0
- package/dist/lib/otel-bridge.js +167 -0
- package/dist/lib/otel-bridge.js.map +1 -0
- package/dist/lib/playground.d.ts +76 -0
- package/dist/lib/playground.d.ts.map +1 -0
- package/dist/lib/playground.js +224 -0
- package/dist/lib/playground.js.map +1 -0
- package/dist/lib/quadtree.d.ts +114 -0
- package/dist/lib/quadtree.d.ts.map +1 -0
- package/dist/lib/quadtree.js +259 -0
- package/dist/lib/quadtree.js.map +1 -0
- package/dist/lib/shared-blackboard.d.ts +101 -0
- package/dist/lib/shared-blackboard.d.ts.map +1 -0
- package/dist/lib/shared-blackboard.js +249 -0
- package/dist/lib/shared-blackboard.js.map +1 -0
- package/dist/lib/speculative-executor.d.ts +89 -0
- package/dist/lib/speculative-executor.d.ts.map +1 -0
- package/dist/lib/speculative-executor.js +107 -0
- package/dist/lib/speculative-executor.js.map +1 -0
- package/dist/lib/swarm-transport.d.ts +150 -0
- package/dist/lib/swarm-transport.d.ts.map +1 -0
- package/dist/lib/swarm-transport.js +307 -0
- package/dist/lib/swarm-transport.js.map +1 -0
- package/dist/lib/task-decomposer.d.ts +41 -0
- package/dist/lib/task-decomposer.d.ts.map +1 -0
- package/dist/lib/task-decomposer.js +272 -0
- package/dist/lib/task-decomposer.js.map +1 -0
- package/dist/lib/timeline-scrubber.d.ts +84 -0
- package/dist/lib/timeline-scrubber.d.ts.map +1 -0
- package/dist/lib/timeline-scrubber.js +173 -0
- package/dist/lib/timeline-scrubber.js.map +1 -0
- package/dist/lib/topology.d.ts +361 -0
- package/dist/lib/topology.d.ts.map +1 -0
- package/dist/lib/topology.js +591 -0
- package/dist/lib/topology.js.map +1 -0
- package/dist/security.d.ts +95 -0
- package/dist/security.d.ts.map +1 -1
- package/dist/security.js +266 -4
- package/dist/security.js.map +1 -1
- package/package.json +7 -5
- package/types/agent-adapter.d.ts +5 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Barnes-Hut QuadTree — Spatial indexing for O(n log n) force simulation
|
|
3
|
+
*
|
|
4
|
+
* Used by the topology dashboard to replace the naive O(n²) all-pairs
|
|
5
|
+
* repulsion with Barnes-Hut approximation. Also provides viewport queries
|
|
6
|
+
* for culling off-screen nodes.
|
|
7
|
+
*
|
|
8
|
+
* @module QuadTree
|
|
9
|
+
* @version 1.0.0
|
|
10
|
+
*/
|
|
11
|
+
/** A 2D point with an identifier */
|
|
12
|
+
export interface QTPoint {
|
|
13
|
+
id: string;
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
}
|
|
17
|
+
/** Axis-aligned bounding box */
|
|
18
|
+
export interface QTBounds {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
halfW: number;
|
|
22
|
+
halfH: number;
|
|
23
|
+
}
|
|
24
|
+
/** Statistics about a QuadTree region (for Barnes-Hut) */
|
|
25
|
+
export interface QTMass {
|
|
26
|
+
/** Total number of points in this region */
|
|
27
|
+
count: number;
|
|
28
|
+
/** Center of mass x */
|
|
29
|
+
cx: number;
|
|
30
|
+
/** Center of mass y */
|
|
31
|
+
cy: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A QuadTree for 2D spatial indexing with Barnes-Hut mass summaries.
|
|
35
|
+
*
|
|
36
|
+
* Usage:
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const qt = new QuadTree({ x: 500, y: 400, halfW: 500, halfH: 400 });
|
|
39
|
+
* qt.insert({ id: 'a', x: 100, y: 200 });
|
|
40
|
+
* qt.insert({ id: 'b', x: 300, y: 150 });
|
|
41
|
+
*
|
|
42
|
+
* // Barnes-Hut force query (theta = 0.5)
|
|
43
|
+
* qt.forceOnPoint(100, 200, 0.5, (cx, cy, mass, dx, dy, distSq) => {
|
|
44
|
+
* // Apply repulsion force from (cx, cy) with given mass
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* // Viewport query
|
|
48
|
+
* const visible = qt.queryRange({ x: 250, y: 250, halfW: 250, halfH: 250 });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare class QuadTree {
|
|
52
|
+
private bounds;
|
|
53
|
+
private points;
|
|
54
|
+
private divided;
|
|
55
|
+
private nw;
|
|
56
|
+
private ne;
|
|
57
|
+
private sw;
|
|
58
|
+
private se;
|
|
59
|
+
private mass;
|
|
60
|
+
constructor(bounds: QTBounds);
|
|
61
|
+
/**
|
|
62
|
+
* Insert a point into the tree.
|
|
63
|
+
* @returns true if inserted, false if out of bounds
|
|
64
|
+
*/
|
|
65
|
+
insert(point: QTPoint): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Build the tree from an array of points (faster than individual inserts).
|
|
68
|
+
*/
|
|
69
|
+
static build(points: QTPoint[], bounds: QTBounds): QuadTree;
|
|
70
|
+
/**
|
|
71
|
+
* Find all points within a rectangular viewport.
|
|
72
|
+
*/
|
|
73
|
+
queryRange(range: QTBounds): QTPoint[];
|
|
74
|
+
private queryRangeInto;
|
|
75
|
+
/**
|
|
76
|
+
* Traverse the tree with Barnes-Hut approximation for a single point.
|
|
77
|
+
*
|
|
78
|
+
* For each region, if the region is "far enough" (width/distance < theta),
|
|
79
|
+
* treat it as a point mass at the center of mass. Otherwise recurse.
|
|
80
|
+
*
|
|
81
|
+
* @param px - Query point x
|
|
82
|
+
* @param py - Query point y
|
|
83
|
+
* @param theta - Opening angle threshold (0.5 is common, higher = faster but less accurate)
|
|
84
|
+
* @param callback - Called for each mass interaction: (cx, cy, mass, dx, dy, distSq)
|
|
85
|
+
*/
|
|
86
|
+
forceOnPoint(px: number, py: number, theta: number, callback: (cx: number, cy: number, mass: number, dx: number, dy: number, distSq: number) => void): void;
|
|
87
|
+
/** Total point count in this subtree */
|
|
88
|
+
get count(): number;
|
|
89
|
+
/** The mass summary of this subtree */
|
|
90
|
+
getMass(): QTMass;
|
|
91
|
+
/** The bounds of this node */
|
|
92
|
+
getBounds(): QTBounds;
|
|
93
|
+
/** Whether this node has been subdivided */
|
|
94
|
+
get isSubdivided(): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Get cluster summaries at a given depth or size threshold.
|
|
97
|
+
* Returns groups of points that share a QuadTree cell below the given size.
|
|
98
|
+
*
|
|
99
|
+
* @param maxCellSize - Maximum cell width to stop recursing (in world units)
|
|
100
|
+
* @returns Array of clusters, each with center, count, and contained point ids
|
|
101
|
+
*/
|
|
102
|
+
getClusters(maxCellSize: number): Array<{
|
|
103
|
+
cx: number;
|
|
104
|
+
cy: number;
|
|
105
|
+
count: number;
|
|
106
|
+
ids: string[];
|
|
107
|
+
}>;
|
|
108
|
+
private collectClusters;
|
|
109
|
+
private collectAllIds;
|
|
110
|
+
private subdivide;
|
|
111
|
+
private containsPoint;
|
|
112
|
+
private intersects;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=quadtree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quadtree.d.ts","sourceRoot":"","sources":["../../lib/quadtree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,oCAAoC;AACpC,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,gCAAgC;AAChC,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,0DAA0D;AAC1D,MAAM,WAAW,MAAM;IACrB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;CACZ;AAQD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,IAAI,CAAsC;gBAEtC,MAAM,EAAE,QAAQ;IAQ5B;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IA2B/B;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,GAAG,QAAQ;IAY3D;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,EAAE;IAMtC,OAAO,CAAC,cAAc;IA0BtB;;;;;;;;;;OAUG;IACH,YAAY,CACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAC/F,IAAI;IAiCP,wCAAwC;IACxC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,uCAAuC;IACvC,OAAO,IAAI,MAAM;IAIjB,8BAA8B;IAC9B,SAAS,IAAI,QAAQ;IAIrB,4CAA4C;IAC5C,IAAI,YAAY,IAAI,OAAO,CAE1B;IAMD;;;;;;OAMG;IACH,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAMjG,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,UAAU;CAQnB"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Barnes-Hut QuadTree — Spatial indexing for O(n log n) force simulation
|
|
4
|
+
*
|
|
5
|
+
* Used by the topology dashboard to replace the naive O(n²) all-pairs
|
|
6
|
+
* repulsion with Barnes-Hut approximation. Also provides viewport queries
|
|
7
|
+
* for culling off-screen nodes.
|
|
8
|
+
*
|
|
9
|
+
* @module QuadTree
|
|
10
|
+
* @version 1.0.0
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.QuadTree = void 0;
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// QUADTREE NODE
|
|
16
|
+
// ============================================================================
|
|
17
|
+
const QT_CAPACITY = 8; // Points per leaf before subdividing
|
|
18
|
+
/**
|
|
19
|
+
* A QuadTree for 2D spatial indexing with Barnes-Hut mass summaries.
|
|
20
|
+
*
|
|
21
|
+
* Usage:
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const qt = new QuadTree({ x: 500, y: 400, halfW: 500, halfH: 400 });
|
|
24
|
+
* qt.insert({ id: 'a', x: 100, y: 200 });
|
|
25
|
+
* qt.insert({ id: 'b', x: 300, y: 150 });
|
|
26
|
+
*
|
|
27
|
+
* // Barnes-Hut force query (theta = 0.5)
|
|
28
|
+
* qt.forceOnPoint(100, 200, 0.5, (cx, cy, mass, dx, dy, distSq) => {
|
|
29
|
+
* // Apply repulsion force from (cx, cy) with given mass
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* // Viewport query
|
|
33
|
+
* const visible = qt.queryRange({ x: 250, y: 250, halfW: 250, halfH: 250 });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
class QuadTree {
|
|
37
|
+
bounds;
|
|
38
|
+
points = [];
|
|
39
|
+
divided = false;
|
|
40
|
+
nw = null;
|
|
41
|
+
ne = null;
|
|
42
|
+
sw = null;
|
|
43
|
+
se = null;
|
|
44
|
+
mass = { count: 0, cx: 0, cy: 0 };
|
|
45
|
+
constructor(bounds) {
|
|
46
|
+
this.bounds = bounds;
|
|
47
|
+
}
|
|
48
|
+
// --------------------------------------------------------------------------
|
|
49
|
+
// INSERTION
|
|
50
|
+
// --------------------------------------------------------------------------
|
|
51
|
+
/**
|
|
52
|
+
* Insert a point into the tree.
|
|
53
|
+
* @returns true if inserted, false if out of bounds
|
|
54
|
+
*/
|
|
55
|
+
insert(point) {
|
|
56
|
+
if (!this.containsPoint(point.x, point.y))
|
|
57
|
+
return false;
|
|
58
|
+
// Update mass center incrementally
|
|
59
|
+
const prev = this.mass.count;
|
|
60
|
+
this.mass.cx = (this.mass.cx * prev + point.x) / (prev + 1);
|
|
61
|
+
this.mass.cy = (this.mass.cy * prev + point.y) / (prev + 1);
|
|
62
|
+
this.mass.count = prev + 1;
|
|
63
|
+
if (!this.divided && this.points.length < QT_CAPACITY) {
|
|
64
|
+
this.points.push(point);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
if (!this.divided) {
|
|
68
|
+
this.subdivide();
|
|
69
|
+
}
|
|
70
|
+
if (this.nw.insert(point))
|
|
71
|
+
return true;
|
|
72
|
+
if (this.ne.insert(point))
|
|
73
|
+
return true;
|
|
74
|
+
if (this.sw.insert(point))
|
|
75
|
+
return true;
|
|
76
|
+
if (this.se.insert(point))
|
|
77
|
+
return true;
|
|
78
|
+
// Shouldn't happen if containsPoint passed, but safety fallback
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Build the tree from an array of points (faster than individual inserts).
|
|
83
|
+
*/
|
|
84
|
+
static build(points, bounds) {
|
|
85
|
+
const tree = new QuadTree(bounds);
|
|
86
|
+
for (const p of points) {
|
|
87
|
+
tree.insert(p);
|
|
88
|
+
}
|
|
89
|
+
return tree;
|
|
90
|
+
}
|
|
91
|
+
// --------------------------------------------------------------------------
|
|
92
|
+
// QUERIES
|
|
93
|
+
// --------------------------------------------------------------------------
|
|
94
|
+
/**
|
|
95
|
+
* Find all points within a rectangular viewport.
|
|
96
|
+
*/
|
|
97
|
+
queryRange(range) {
|
|
98
|
+
const found = [];
|
|
99
|
+
this.queryRangeInto(range, found);
|
|
100
|
+
return found;
|
|
101
|
+
}
|
|
102
|
+
queryRangeInto(range, found) {
|
|
103
|
+
if (!this.intersects(range))
|
|
104
|
+
return;
|
|
105
|
+
for (const p of this.points) {
|
|
106
|
+
if (p.x >= range.x - range.halfW &&
|
|
107
|
+
p.x <= range.x + range.halfW &&
|
|
108
|
+
p.y >= range.y - range.halfH &&
|
|
109
|
+
p.y <= range.y + range.halfH) {
|
|
110
|
+
found.push(p);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (this.divided) {
|
|
114
|
+
this.nw.queryRangeInto(range, found);
|
|
115
|
+
this.ne.queryRangeInto(range, found);
|
|
116
|
+
this.sw.queryRangeInto(range, found);
|
|
117
|
+
this.se.queryRangeInto(range, found);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// --------------------------------------------------------------------------
|
|
121
|
+
// BARNES-HUT FORCE TRAVERSAL
|
|
122
|
+
// --------------------------------------------------------------------------
|
|
123
|
+
/**
|
|
124
|
+
* Traverse the tree with Barnes-Hut approximation for a single point.
|
|
125
|
+
*
|
|
126
|
+
* For each region, if the region is "far enough" (width/distance < theta),
|
|
127
|
+
* treat it as a point mass at the center of mass. Otherwise recurse.
|
|
128
|
+
*
|
|
129
|
+
* @param px - Query point x
|
|
130
|
+
* @param py - Query point y
|
|
131
|
+
* @param theta - Opening angle threshold (0.5 is common, higher = faster but less accurate)
|
|
132
|
+
* @param callback - Called for each mass interaction: (cx, cy, mass, dx, dy, distSq)
|
|
133
|
+
*/
|
|
134
|
+
forceOnPoint(px, py, theta, callback) {
|
|
135
|
+
if (this.mass.count === 0)
|
|
136
|
+
return;
|
|
137
|
+
const dx = this.mass.cx - px;
|
|
138
|
+
const dy = this.mass.cy - py;
|
|
139
|
+
const distSq = dx * dx + dy * dy;
|
|
140
|
+
// If this is a leaf with points, interact directly
|
|
141
|
+
if (!this.divided) {
|
|
142
|
+
if (distSq > 0.01) {
|
|
143
|
+
callback(this.mass.cx, this.mass.cy, this.mass.count, dx, dy, distSq);
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// Barnes-Hut criterion: region width / distance < theta → approximate
|
|
148
|
+
const regionWidth = this.bounds.halfW * 2;
|
|
149
|
+
if (regionWidth * regionWidth < theta * theta * distSq) {
|
|
150
|
+
callback(this.mass.cx, this.mass.cy, this.mass.count, dx, dy, distSq);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// Recurse into children
|
|
154
|
+
this.nw.forceOnPoint(px, py, theta, callback);
|
|
155
|
+
this.ne.forceOnPoint(px, py, theta, callback);
|
|
156
|
+
this.sw.forceOnPoint(px, py, theta, callback);
|
|
157
|
+
this.se.forceOnPoint(px, py, theta, callback);
|
|
158
|
+
}
|
|
159
|
+
// --------------------------------------------------------------------------
|
|
160
|
+
// ACCESSORS
|
|
161
|
+
// --------------------------------------------------------------------------
|
|
162
|
+
/** Total point count in this subtree */
|
|
163
|
+
get count() {
|
|
164
|
+
return this.mass.count;
|
|
165
|
+
}
|
|
166
|
+
/** The mass summary of this subtree */
|
|
167
|
+
getMass() {
|
|
168
|
+
return { ...this.mass };
|
|
169
|
+
}
|
|
170
|
+
/** The bounds of this node */
|
|
171
|
+
getBounds() {
|
|
172
|
+
return { ...this.bounds };
|
|
173
|
+
}
|
|
174
|
+
/** Whether this node has been subdivided */
|
|
175
|
+
get isSubdivided() {
|
|
176
|
+
return this.divided;
|
|
177
|
+
}
|
|
178
|
+
// --------------------------------------------------------------------------
|
|
179
|
+
// CLUSTERING SUPPORT
|
|
180
|
+
// --------------------------------------------------------------------------
|
|
181
|
+
/**
|
|
182
|
+
* Get cluster summaries at a given depth or size threshold.
|
|
183
|
+
* Returns groups of points that share a QuadTree cell below the given size.
|
|
184
|
+
*
|
|
185
|
+
* @param maxCellSize - Maximum cell width to stop recursing (in world units)
|
|
186
|
+
* @returns Array of clusters, each with center, count, and contained point ids
|
|
187
|
+
*/
|
|
188
|
+
getClusters(maxCellSize) {
|
|
189
|
+
const clusters = [];
|
|
190
|
+
this.collectClusters(maxCellSize, clusters);
|
|
191
|
+
return clusters;
|
|
192
|
+
}
|
|
193
|
+
collectClusters(maxCellSize, out) {
|
|
194
|
+
if (this.mass.count === 0)
|
|
195
|
+
return;
|
|
196
|
+
const cellSize = this.bounds.halfW * 2;
|
|
197
|
+
// If this cell is small enough OR is a leaf, emit as cluster
|
|
198
|
+
if (cellSize <= maxCellSize || !this.divided) {
|
|
199
|
+
const ids = this.collectAllIds();
|
|
200
|
+
if (ids.length > 0) {
|
|
201
|
+
out.push({
|
|
202
|
+
cx: this.mass.cx,
|
|
203
|
+
cy: this.mass.cy,
|
|
204
|
+
count: this.mass.count,
|
|
205
|
+
ids,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
this.nw.collectClusters(maxCellSize, out);
|
|
211
|
+
this.ne.collectClusters(maxCellSize, out);
|
|
212
|
+
this.sw.collectClusters(maxCellSize, out);
|
|
213
|
+
this.se.collectClusters(maxCellSize, out);
|
|
214
|
+
}
|
|
215
|
+
collectAllIds() {
|
|
216
|
+
const ids = [];
|
|
217
|
+
for (const p of this.points)
|
|
218
|
+
ids.push(p.id);
|
|
219
|
+
if (this.divided) {
|
|
220
|
+
ids.push(...this.nw.collectAllIds());
|
|
221
|
+
ids.push(...this.ne.collectAllIds());
|
|
222
|
+
ids.push(...this.sw.collectAllIds());
|
|
223
|
+
ids.push(...this.se.collectAllIds());
|
|
224
|
+
}
|
|
225
|
+
return ids;
|
|
226
|
+
}
|
|
227
|
+
// --------------------------------------------------------------------------
|
|
228
|
+
// INTERNALS
|
|
229
|
+
// --------------------------------------------------------------------------
|
|
230
|
+
subdivide() {
|
|
231
|
+
const { x, y, halfW, halfH } = this.bounds;
|
|
232
|
+
const qW = halfW / 2;
|
|
233
|
+
const qH = halfH / 2;
|
|
234
|
+
this.nw = new QuadTree({ x: x - qW, y: y - qH, halfW: qW, halfH: qH });
|
|
235
|
+
this.ne = new QuadTree({ x: x + qW, y: y - qH, halfW: qW, halfH: qH });
|
|
236
|
+
this.sw = new QuadTree({ x: x - qW, y: y + qH, halfW: qW, halfH: qH });
|
|
237
|
+
this.se = new QuadTree({ x: x + qW, y: y + qH, halfW: qW, halfH: qH });
|
|
238
|
+
// Re-insert existing points into children
|
|
239
|
+
for (const p of this.points) {
|
|
240
|
+
this.nw.insert(p) || this.ne.insert(p) || this.sw.insert(p) || this.se.insert(p);
|
|
241
|
+
}
|
|
242
|
+
this.points = [];
|
|
243
|
+
this.divided = true;
|
|
244
|
+
}
|
|
245
|
+
containsPoint(x, y) {
|
|
246
|
+
return (x >= this.bounds.x - this.bounds.halfW &&
|
|
247
|
+
x <= this.bounds.x + this.bounds.halfW &&
|
|
248
|
+
y >= this.bounds.y - this.bounds.halfH &&
|
|
249
|
+
y <= this.bounds.y + this.bounds.halfH);
|
|
250
|
+
}
|
|
251
|
+
intersects(range) {
|
|
252
|
+
return !(range.x - range.halfW > this.bounds.x + this.bounds.halfW ||
|
|
253
|
+
range.x + range.halfW < this.bounds.x - this.bounds.halfW ||
|
|
254
|
+
range.y - range.halfH > this.bounds.y + this.bounds.halfH ||
|
|
255
|
+
range.y + range.halfH < this.bounds.y - this.bounds.halfH);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
exports.QuadTree = QuadTree;
|
|
259
|
+
//# sourceMappingURL=quadtree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quadtree.js","sourceRoot":"","sources":["../../lib/quadtree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Namespace-scoped, identity-verified shared state for multi-agent coordination.
|
|
3
|
+
*
|
|
4
|
+
* Every write is identity-verified (agent token), namespace-checked,
|
|
5
|
+
* size-validated, input-sanitized, and atomically persisted through
|
|
6
|
+
* the pluggable {@link BlackboardBackend}.
|
|
7
|
+
*
|
|
8
|
+
* @module SharedBlackboard
|
|
9
|
+
*/
|
|
10
|
+
import type { BlackboardBackend } from './blackboard-backend';
|
|
11
|
+
import type { BlackboardEntry } from './orchestrator-types';
|
|
12
|
+
/**
|
|
13
|
+
* Namespace-scoped, identity-verified shared state for multi-agent coordination.
|
|
14
|
+
*
|
|
15
|
+
* Every write is identity-verified (agent token), namespace-checked,
|
|
16
|
+
* size-validated, input-sanitized, and atomically persisted through
|
|
17
|
+
* {@link LockedBlackboard}.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const bb = new SharedBlackboard('./workspace');
|
|
22
|
+
* bb.registerAgent('analyst', 'secret-token', ['task:', 'analytics:']);
|
|
23
|
+
* bb.write('task:revenue', { q4: 42_000 }, 'analyst', 3600, 'secret-token');
|
|
24
|
+
* const entry = bb.read('task:revenue');
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class SharedBlackboard {
|
|
28
|
+
private backend;
|
|
29
|
+
private agentTokens;
|
|
30
|
+
private agentNamespaces;
|
|
31
|
+
private piiRedactor;
|
|
32
|
+
constructor(backendOrPath: string | BlackboardBackend, options?: {
|
|
33
|
+
enablePIIRedaction?: boolean;
|
|
34
|
+
});
|
|
35
|
+
/**
|
|
36
|
+
* Enable or disable PII redaction on writes.
|
|
37
|
+
*/
|
|
38
|
+
setPIIRedaction(enabled: boolean): void;
|
|
39
|
+
/**
|
|
40
|
+
* Register a verified agent identity. Only agents with registered tokens
|
|
41
|
+
* can write to the blackboard. The orchestrator registers agents after
|
|
42
|
+
* verifying their identity through the AuthGuardian.
|
|
43
|
+
*/
|
|
44
|
+
registerAgent(agentId: string, verificationToken: string, allowedNamespaces?: string[]): void;
|
|
45
|
+
/**
|
|
46
|
+
* Check if an agent is allowed to access a key based on namespace rules.
|
|
47
|
+
*/
|
|
48
|
+
private canAccessKey;
|
|
49
|
+
/**
|
|
50
|
+
* Verify that the calling agent is who they claim to be.
|
|
51
|
+
*/
|
|
52
|
+
private verifyAgent;
|
|
53
|
+
/**
|
|
54
|
+
* Validate value size and structure before writing.
|
|
55
|
+
* Prevents DoS via oversized writes and circular data.
|
|
56
|
+
*/
|
|
57
|
+
private validateValue;
|
|
58
|
+
/**
|
|
59
|
+
* Sanitize a key to prevent markdown injection.
|
|
60
|
+
*/
|
|
61
|
+
private sanitizeKey;
|
|
62
|
+
/**
|
|
63
|
+
* Read an entry from the blackboard by key.
|
|
64
|
+
*
|
|
65
|
+
* @param key - The entry key to look up
|
|
66
|
+
* @returns The entry, or `null` if not found or expired
|
|
67
|
+
* @throws {@link ValidationError} if `key` is not a non-empty string
|
|
68
|
+
*/
|
|
69
|
+
read(key: string): BlackboardEntry | null;
|
|
70
|
+
/**
|
|
71
|
+
* Write to the blackboard with identity verification, namespace checks,
|
|
72
|
+
* value validation, and input sanitization. Uses LockedBlackboard for
|
|
73
|
+
* atomic file-system writes.
|
|
74
|
+
*
|
|
75
|
+
* @param key - The key to write
|
|
76
|
+
* @param value - The value (will be sanitized and size-checked)
|
|
77
|
+
* @param sourceAgent - Agent claiming to write (verified against registered token)
|
|
78
|
+
* @param ttl - Optional TTL in seconds
|
|
79
|
+
* @param agentToken - Optional verification token for identity check
|
|
80
|
+
*/
|
|
81
|
+
write(key: string, value: unknown, sourceAgent: string, ttl?: number, agentToken?: string): BlackboardEntry;
|
|
82
|
+
/**
|
|
83
|
+
* Check whether a key exists on the blackboard (not expired).
|
|
84
|
+
* @param key - The entry key to check
|
|
85
|
+
*/
|
|
86
|
+
exists(key: string): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Get a full snapshot of all blackboard entries.
|
|
89
|
+
*/
|
|
90
|
+
getSnapshot(): Record<string, BlackboardEntry>;
|
|
91
|
+
/**
|
|
92
|
+
* Get a namespace-scoped snapshot -- only returns keys an agent is allowed to see.
|
|
93
|
+
* Prevents data leakage between agents.
|
|
94
|
+
*/
|
|
95
|
+
getScopedSnapshot(agentId: string): Record<string, BlackboardEntry>;
|
|
96
|
+
/**
|
|
97
|
+
* Clear all entries (for testing).
|
|
98
|
+
*/
|
|
99
|
+
clear(): void;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=shared-blackboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-blackboard.d.ts","sourceRoot":"","sources":["../../lib/shared-blackboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAQ9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,WAAW,CAA4B;gBAEnC,aAAa,EAAE,MAAM,GAAG,iBAAiB,EAAE,OAAO,CAAC,EAAE;QAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE;IAiBjG;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIvC;;;;OAIG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,GAAE,MAAM,EAAU,GAAG,IAAI;IAcpG;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACH,OAAO,CAAC,WAAW;IAOnB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAYrB;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;;;;;OAMG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAgBzC;;;;;;;;;;OAUG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe;IA+C3G;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B;;OAEG;IACH,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;IAe9C;;;OAGG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;IAcnE;;OAEG;IACH,KAAK,IAAI,IAAI;CAOd"}
|