network-ai 5.10.2 → 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,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Task decomposition engine for parallel multi-agent execution.
|
|
4
|
+
*
|
|
5
|
+
* Breaks complex tasks into parallel sub-agent calls, routes them through
|
|
6
|
+
* the adapter registry, caches results on the blackboard, and synthesizes
|
|
7
|
+
* outputs using configurable strategies (merge, vote, chain, first-success).
|
|
8
|
+
*
|
|
9
|
+
* @module TaskDecomposer
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.TaskDecomposer = void 0;
|
|
13
|
+
const crypto_1 = require("crypto");
|
|
14
|
+
const adapter_registry_1 = require("../adapters/adapter-registry");
|
|
15
|
+
const security_1 = require("../security");
|
|
16
|
+
const errors_1 = require("./errors");
|
|
17
|
+
const shared_blackboard_1 = require("./shared-blackboard");
|
|
18
|
+
const auth_guardian_1 = require("./auth-guardian");
|
|
19
|
+
const orchestrator_types_1 = require("./orchestrator-types");
|
|
20
|
+
class TaskDecomposer {
|
|
21
|
+
blackboard;
|
|
22
|
+
authGuardian;
|
|
23
|
+
adapterRegistry;
|
|
24
|
+
/** Maximum number of tasks to run concurrently (0 = unlimited). */
|
|
25
|
+
maxConcurrency;
|
|
26
|
+
constructor(blackboard, authGuardian, adapterRegistry, options) {
|
|
27
|
+
if (!blackboard || !(blackboard instanceof shared_blackboard_1.SharedBlackboard)) {
|
|
28
|
+
throw new errors_1.ValidationError('blackboard must be an instance of SharedBlackboard');
|
|
29
|
+
}
|
|
30
|
+
if (!authGuardian || !(authGuardian instanceof auth_guardian_1.AuthGuardian)) {
|
|
31
|
+
throw new errors_1.ValidationError('authGuardian must be an instance of AuthGuardian');
|
|
32
|
+
}
|
|
33
|
+
if (!adapterRegistry || !(adapterRegistry instanceof adapter_registry_1.AdapterRegistry)) {
|
|
34
|
+
throw new errors_1.ValidationError('adapterRegistry must be an instance of AdapterRegistry');
|
|
35
|
+
}
|
|
36
|
+
this.blackboard = blackboard;
|
|
37
|
+
this.authGuardian = authGuardian;
|
|
38
|
+
this.adapterRegistry = adapterRegistry;
|
|
39
|
+
this.maxConcurrency = options?.maxConcurrency ?? 5;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Decomposes a complex task into parallel sub-agent calls
|
|
43
|
+
* This is the "Wall Breaker" - transforms impossible monolithic tasks
|
|
44
|
+
* into manageable parallel executions
|
|
45
|
+
*/
|
|
46
|
+
async executeParallel(tasks, synthesisStrategy = 'merge', context) {
|
|
47
|
+
if (!tasks || !Array.isArray(tasks)) {
|
|
48
|
+
throw new errors_1.ValidationError('tasks must be an array');
|
|
49
|
+
}
|
|
50
|
+
if (tasks.length === 0) {
|
|
51
|
+
throw new errors_1.ValidationError('tasks array must not be empty');
|
|
52
|
+
}
|
|
53
|
+
if (!context || typeof context !== 'object' || !context.agentId) {
|
|
54
|
+
throw new errors_1.ValidationError('context is required and must include agentId');
|
|
55
|
+
}
|
|
56
|
+
// No hard parallel limit — caller controls concurrency via task count
|
|
57
|
+
const startTime = Date.now();
|
|
58
|
+
const individualResults = [];
|
|
59
|
+
// Check blackboard for cached results first
|
|
60
|
+
const cachedTasks = [];
|
|
61
|
+
const uncachedTasks = [];
|
|
62
|
+
for (const task of tasks) {
|
|
63
|
+
const cacheKey = `task:${task.agentType}:${this.hashPayload(task.taskPayload)}`;
|
|
64
|
+
const cached = this.blackboard.read(cacheKey);
|
|
65
|
+
if (cached) {
|
|
66
|
+
individualResults.push({
|
|
67
|
+
agentType: task.agentType,
|
|
68
|
+
success: true,
|
|
69
|
+
result: cached.value,
|
|
70
|
+
executionTime: 0, // From cache
|
|
71
|
+
});
|
|
72
|
+
cachedTasks.push(task);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
uncachedTasks.push(task);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Execute uncached tasks with concurrency cap
|
|
79
|
+
if (uncachedTasks.length > 0) {
|
|
80
|
+
const results = await this.runWithConcurrencyLimit(uncachedTasks, task => this.executeSingleTask(task, context), this.maxConcurrency);
|
|
81
|
+
for (let i = 0; i < results.length; i++) {
|
|
82
|
+
const task = uncachedTasks[i];
|
|
83
|
+
const result = results[i];
|
|
84
|
+
individualResults.push(result);
|
|
85
|
+
// Cache successful results
|
|
86
|
+
if (result.success) {
|
|
87
|
+
const cacheKey = `task:${task.agentType}:${this.hashPayload(task.taskPayload)}`;
|
|
88
|
+
this.blackboard.write(cacheKey, result.result, context.agentId, 3600, 'system-orchestrator-token'); // 1 hour TTL
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Synthesize results based on strategy
|
|
93
|
+
const synthesizedResult = this.synthesize(individualResults, synthesisStrategy);
|
|
94
|
+
const totalTime = Date.now() - startTime;
|
|
95
|
+
const successCount = individualResults.filter(r => r.success).length;
|
|
96
|
+
return {
|
|
97
|
+
synthesizedResult,
|
|
98
|
+
individualResults,
|
|
99
|
+
executionMetrics: {
|
|
100
|
+
totalTime,
|
|
101
|
+
successRate: successCount / individualResults.length,
|
|
102
|
+
synthesisStrategy,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async executeSingleTask(task, context) {
|
|
107
|
+
const taskStart = Date.now();
|
|
108
|
+
try {
|
|
109
|
+
// Build the handoff message
|
|
110
|
+
const handoff = {
|
|
111
|
+
handoffId: (0, crypto_1.randomUUID)(),
|
|
112
|
+
sourceAgent: context.agentId,
|
|
113
|
+
targetAgent: task.agentType,
|
|
114
|
+
taskType: 'delegate',
|
|
115
|
+
payload: task.taskPayload,
|
|
116
|
+
metadata: {
|
|
117
|
+
priority: 1,
|
|
118
|
+
deadline: Date.now() + orchestrator_types_1.CONFIG.defaultTimeout,
|
|
119
|
+
parentTaskId: context.taskId ?? null,
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
// Sanitize the instruction before sending to adapter
|
|
123
|
+
let sanitizedInstruction = task.taskPayload.instruction;
|
|
124
|
+
try {
|
|
125
|
+
sanitizedInstruction = security_1.InputSanitizer.sanitizeString(task.taskPayload.instruction, 10000);
|
|
126
|
+
}
|
|
127
|
+
catch { /* use original if sanitization fails */ }
|
|
128
|
+
// Use namespace-scoped snapshot -- target agent only sees keys it's allowed to see
|
|
129
|
+
const scopedSnapshot = this.blackboard.getScopedSnapshot(task.agentType);
|
|
130
|
+
// Route through the adapter registry (framework-agnostic)
|
|
131
|
+
const agentPayload = {
|
|
132
|
+
action: 'execute',
|
|
133
|
+
params: {},
|
|
134
|
+
handoff: {
|
|
135
|
+
handoffId: handoff.handoffId,
|
|
136
|
+
sourceAgent: handoff.sourceAgent,
|
|
137
|
+
targetAgent: handoff.targetAgent,
|
|
138
|
+
taskType: handoff.taskType,
|
|
139
|
+
instruction: sanitizedInstruction,
|
|
140
|
+
context: handoff.payload.context,
|
|
141
|
+
constraints: handoff.payload.constraints,
|
|
142
|
+
expectedOutput: handoff.payload.expectedOutput,
|
|
143
|
+
metadata: handoff.metadata,
|
|
144
|
+
},
|
|
145
|
+
blackboardSnapshot: scopedSnapshot,
|
|
146
|
+
};
|
|
147
|
+
const agentContext = {
|
|
148
|
+
agentId: context.agentId,
|
|
149
|
+
taskId: context.taskId,
|
|
150
|
+
sessionId: context.sessionId,
|
|
151
|
+
};
|
|
152
|
+
const result = await this.adapterRegistry.executeAgent(task.agentType, agentPayload, agentContext);
|
|
153
|
+
// Sanitize adapter output before returning/caching
|
|
154
|
+
let sanitizedData = result.data;
|
|
155
|
+
try {
|
|
156
|
+
sanitizedData = security_1.InputSanitizer.sanitizeObject(result.data);
|
|
157
|
+
}
|
|
158
|
+
catch { /* use raw if sanitization fails */ }
|
|
159
|
+
return {
|
|
160
|
+
agentType: task.agentType,
|
|
161
|
+
success: true,
|
|
162
|
+
result: sanitizedData,
|
|
163
|
+
executionTime: Date.now() - taskStart,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
return {
|
|
168
|
+
agentType: task.agentType,
|
|
169
|
+
success: false,
|
|
170
|
+
result: {
|
|
171
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
172
|
+
recoverable: true,
|
|
173
|
+
},
|
|
174
|
+
executionTime: Date.now() - taskStart,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
synthesize(results, strategy) {
|
|
179
|
+
const successfulResults = results.filter(r => r.success);
|
|
180
|
+
if (successfulResults.length === 0) {
|
|
181
|
+
return {
|
|
182
|
+
error: 'All parallel tasks failed',
|
|
183
|
+
individualErrors: results.map(r => ({
|
|
184
|
+
agent: r.agentType,
|
|
185
|
+
error: r.result,
|
|
186
|
+
})),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
switch (strategy) {
|
|
190
|
+
case 'merge':
|
|
191
|
+
// Combine all results into a unified object
|
|
192
|
+
return {
|
|
193
|
+
merged: true,
|
|
194
|
+
contributions: successfulResults.map(r => ({
|
|
195
|
+
source: r.agentType,
|
|
196
|
+
data: r.result,
|
|
197
|
+
})),
|
|
198
|
+
summary: this.generateMergeSummary(successfulResults),
|
|
199
|
+
};
|
|
200
|
+
case 'vote':
|
|
201
|
+
// Return the result with highest "confidence" (simplified: most data)
|
|
202
|
+
const scored = successfulResults.map(r => ({
|
|
203
|
+
result: r,
|
|
204
|
+
score: JSON.stringify(r.result).length,
|
|
205
|
+
}));
|
|
206
|
+
scored.sort((a, b) => b.score - a.score);
|
|
207
|
+
return {
|
|
208
|
+
voted: true,
|
|
209
|
+
winner: scored[0].result.agentType,
|
|
210
|
+
result: scored[0].result.result,
|
|
211
|
+
};
|
|
212
|
+
case 'chain':
|
|
213
|
+
// Results should already be ordered; return the final one
|
|
214
|
+
return {
|
|
215
|
+
chained: true,
|
|
216
|
+
finalResult: successfulResults[successfulResults.length - 1].result,
|
|
217
|
+
chainLength: successfulResults.length,
|
|
218
|
+
};
|
|
219
|
+
case 'first-success':
|
|
220
|
+
// Return the first successful result
|
|
221
|
+
return {
|
|
222
|
+
firstSuccess: true,
|
|
223
|
+
source: successfulResults[0].agentType,
|
|
224
|
+
result: successfulResults[0].result,
|
|
225
|
+
};
|
|
226
|
+
default:
|
|
227
|
+
return successfulResults.map(r => r.result);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
generateMergeSummary(results) {
|
|
231
|
+
const agents = results.map(r => r.agentType).join(', ');
|
|
232
|
+
return `Synthesized from ${results.length} agents: ${agents}`;
|
|
233
|
+
}
|
|
234
|
+
hashPayload(payload) {
|
|
235
|
+
// Simple hash for cache key generation
|
|
236
|
+
const str = JSON.stringify(payload);
|
|
237
|
+
let hash = 0;
|
|
238
|
+
for (let i = 0; i < str.length; i++) {
|
|
239
|
+
const char = str.charCodeAt(i);
|
|
240
|
+
hash = ((hash << 5) - hash) + char;
|
|
241
|
+
hash = hash & hash;
|
|
242
|
+
}
|
|
243
|
+
return Math.abs(hash).toString(16);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Execute async functions with a bounded concurrency pool.
|
|
247
|
+
* @param items Items to process
|
|
248
|
+
* @param fn Async function to apply to each item
|
|
249
|
+
* @param limit Max concurrent executions (0 = unlimited)
|
|
250
|
+
*/
|
|
251
|
+
async runWithConcurrencyLimit(items, fn, limit) {
|
|
252
|
+
if (limit <= 0 || items.length <= limit) {
|
|
253
|
+
return Promise.all(items.map(fn));
|
|
254
|
+
}
|
|
255
|
+
const results = new Array(items.length);
|
|
256
|
+
let nextIndex = 0;
|
|
257
|
+
async function worker() {
|
|
258
|
+
while (nextIndex < items.length) {
|
|
259
|
+
const idx = nextIndex++;
|
|
260
|
+
results[idx] = await fn(items[idx]);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const workers = [];
|
|
264
|
+
for (let i = 0; i < Math.min(limit, items.length); i++) {
|
|
265
|
+
workers.push(worker());
|
|
266
|
+
}
|
|
267
|
+
await Promise.all(workers);
|
|
268
|
+
return results;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
exports.TaskDecomposer = TaskDecomposer;
|
|
272
|
+
//# sourceMappingURL=task-decomposer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-decomposer.js","sourceRoot":"","sources":["../../../lib/task-decomposer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Telemetry Provider — BYOT (Bring Your Own Telemetry) abstraction.
|
|
4
|
+
*
|
|
5
|
+
* Defines a minimal interface over distributed tracing providers such as
|
|
6
|
+
* OpenTelemetry, Datadog APM, Honeycomb, etc. Network-AI core never imports
|
|
7
|
+
* a concrete telemetry SDK — only this interface — preserving the zero-
|
|
8
|
+
* dependency BYOC design.
|
|
9
|
+
*
|
|
10
|
+
* ## Wiring into adapter lifecycle hooks
|
|
11
|
+
*
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import { createOtelHooks, CapturingTelemetryProvider } from 'network-ai';
|
|
14
|
+
* import { AdapterHookManager } from 'network-ai';
|
|
15
|
+
*
|
|
16
|
+
* const provider = new CapturingTelemetryProvider(); // or your own impl
|
|
17
|
+
* const hookManager = new AdapterHookManager();
|
|
18
|
+
* createOtelHooks(provider).forEach(h => hookManager.register(h));
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* ## Implementing for OpenTelemetry
|
|
22
|
+
*
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { trace, SpanStatusCode } from '@opentelemetry/api';
|
|
25
|
+
* import type { ITelemetryProvider, SpanAttributes } from 'network-ai';
|
|
26
|
+
*
|
|
27
|
+
* class OtelProvider implements ITelemetryProvider {
|
|
28
|
+
* private tracer = trace.getTracer('network-ai');
|
|
29
|
+
* private spans = new Map<string, Span>();
|
|
30
|
+
*
|
|
31
|
+
* startSpan(name: string, attrs: SpanAttributes = {}): string {
|
|
32
|
+
* const span = this.tracer.startSpan(name, { attributes: attrs as Attributes });
|
|
33
|
+
* const id = `span_${Date.now()}`;
|
|
34
|
+
* this.spans.set(id, span);
|
|
35
|
+
* return id;
|
|
36
|
+
* }
|
|
37
|
+
* endSpan(id: string, status: 'ok' | 'error'): void {
|
|
38
|
+
* const span = this.spans.get(id);
|
|
39
|
+
* if (!span) return;
|
|
40
|
+
* span.setStatus({ code: status === 'ok' ? SpanStatusCode.OK : SpanStatusCode.ERROR });
|
|
41
|
+
* span.end();
|
|
42
|
+
* this.spans.delete(id);
|
|
43
|
+
* }
|
|
44
|
+
* recordEvent(id: string, name: string, attrs: SpanAttributes = {}): void {
|
|
45
|
+
* this.spans.get(id)?.addEvent(name, attrs as Attributes);
|
|
46
|
+
* }
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.CapturingTelemetryProvider = exports.NullTelemetryProvider = void 0;
|
|
52
|
+
exports.createOtelHooks = createOtelHooks;
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// NULL PROVIDER (default — zero overhead when no telemetry is configured)
|
|
55
|
+
// ============================================================================
|
|
56
|
+
/**
|
|
57
|
+
* No-op implementation. Used as the default when no telemetry provider is
|
|
58
|
+
* supplied so the instrumentation path compiles to a handful of dead calls
|
|
59
|
+
* that the JIT eliminates.
|
|
60
|
+
*/
|
|
61
|
+
class NullTelemetryProvider {
|
|
62
|
+
/** @inheritdoc */
|
|
63
|
+
startSpan(_name, _attributes) { return ''; }
|
|
64
|
+
/** @inheritdoc */
|
|
65
|
+
endSpan(_spanId, _status, _attributes) { }
|
|
66
|
+
/** @inheritdoc */
|
|
67
|
+
recordEvent(_spanId, _name, _attributes) { }
|
|
68
|
+
}
|
|
69
|
+
exports.NullTelemetryProvider = NullTelemetryProvider;
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// CAPTURING PROVIDER (for testing)
|
|
72
|
+
// ============================================================================
|
|
73
|
+
/**
|
|
74
|
+
* In-memory provider that stores every span and event for test assertions.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const provider = new CapturingTelemetryProvider();
|
|
79
|
+
* createOtelHooks(provider).forEach(h => hookManager.register(h));
|
|
80
|
+
*
|
|
81
|
+
* await registry.executeAgent('agent:foo', payload, ctx);
|
|
82
|
+
*
|
|
83
|
+
* const span = provider.spans.find(s => s.name === 'adapter.execute');
|
|
84
|
+
* expect(span?.status).toBe('ok');
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
class CapturingTelemetryProvider {
|
|
88
|
+
/** All spans created since construction or last `clear()`. */
|
|
89
|
+
spans = [];
|
|
90
|
+
counter = 0;
|
|
91
|
+
/** @inheritdoc */
|
|
92
|
+
startSpan(name, attributes = {}) {
|
|
93
|
+
const spanId = `span_${++this.counter}`;
|
|
94
|
+
this.spans.push({ spanId, name, attributes: { ...attributes }, startedAt: Date.now(), events: [] });
|
|
95
|
+
return spanId;
|
|
96
|
+
}
|
|
97
|
+
/** @inheritdoc */
|
|
98
|
+
endSpan(spanId, status, attributes = {}) {
|
|
99
|
+
const span = this.spans.find(s => s.spanId === spanId);
|
|
100
|
+
if (!span)
|
|
101
|
+
return;
|
|
102
|
+
span.endedAt = Date.now();
|
|
103
|
+
span.status = status;
|
|
104
|
+
Object.assign(span.attributes, attributes);
|
|
105
|
+
}
|
|
106
|
+
/** @inheritdoc */
|
|
107
|
+
recordEvent(spanId, name, attributes = {}) {
|
|
108
|
+
const span = this.spans.find(s => s.spanId === spanId);
|
|
109
|
+
if (!span)
|
|
110
|
+
return;
|
|
111
|
+
span.events.push({ name, attributes: { ...attributes }, ts: Date.now() });
|
|
112
|
+
}
|
|
113
|
+
/** Clear all captured data and reset span counter. */
|
|
114
|
+
clear() {
|
|
115
|
+
this.spans.length = 0;
|
|
116
|
+
this.counter = 0;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
exports.CapturingTelemetryProvider = CapturingTelemetryProvider;
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// HOOK FACTORY
|
|
122
|
+
// ============================================================================
|
|
123
|
+
/** Metadata key used to propagate spanId through `HookContext`. @internal */
|
|
124
|
+
const SPAN_ID_META_KEY = '_otelSpanId';
|
|
125
|
+
/**
|
|
126
|
+
* Create a set of `ExecutionHook` objects that emit traces to `provider`.
|
|
127
|
+
*
|
|
128
|
+
* Register the returned hooks with an `AdapterHookManager`:
|
|
129
|
+
* ```typescript
|
|
130
|
+
* createOtelHooks(provider).forEach(h => hookManager.register(h));
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* Three hooks are created — one per `HookPhase`:
|
|
134
|
+
* - `otel:beforeExecute` — calls `provider.startSpan('adapter.execute', {...})`
|
|
135
|
+
* - `otel:afterExecute` — calls `provider.endSpan(spanId, 'ok')`
|
|
136
|
+
* - `otel:onError` — calls `provider.endSpan(spanId, 'error')`
|
|
137
|
+
*
|
|
138
|
+
* Each hook has `priority: 100` so it runs before most user-defined hooks.
|
|
139
|
+
* The spanId is stored in `ctx.metadata._otelSpanId` for downstream hooks
|
|
140
|
+
* that wish to add their own `recordEvent` calls.
|
|
141
|
+
*
|
|
142
|
+
* **Permission check semantics:** `beforeExecute` fires once when execution
|
|
143
|
+
* begins — not per streaming chunk — matching the documented "once at start"
|
|
144
|
+
* semantics of `StreamingBaseAdapter`.
|
|
145
|
+
*/
|
|
146
|
+
function createOtelHooks(provider) {
|
|
147
|
+
return [
|
|
148
|
+
{
|
|
149
|
+
name: 'otel:beforeExecute',
|
|
150
|
+
phase: 'beforeExecute',
|
|
151
|
+
priority: 100,
|
|
152
|
+
handler(ctx) {
|
|
153
|
+
try {
|
|
154
|
+
const spanId = provider.startSpan('adapter.execute', {
|
|
155
|
+
agentId: ctx.agentId,
|
|
156
|
+
action: ctx.payload.action ?? '',
|
|
157
|
+
depth: ctx.depth,
|
|
158
|
+
});
|
|
159
|
+
ctx.metadata[SPAN_ID_META_KEY] = spanId;
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Telemetry must never break execution
|
|
163
|
+
}
|
|
164
|
+
return ctx;
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'otel:afterExecute',
|
|
169
|
+
phase: 'afterExecute',
|
|
170
|
+
priority: 100,
|
|
171
|
+
handler(ctx) {
|
|
172
|
+
try {
|
|
173
|
+
const spanId = ctx.metadata[SPAN_ID_META_KEY];
|
|
174
|
+
if (spanId) {
|
|
175
|
+
provider.endSpan(spanId, 'ok', {
|
|
176
|
+
success: ctx.result?.success === true,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// no-op
|
|
182
|
+
}
|
|
183
|
+
return ctx;
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: 'otel:onError',
|
|
188
|
+
phase: 'onError',
|
|
189
|
+
priority: 100,
|
|
190
|
+
handler(ctx) {
|
|
191
|
+
try {
|
|
192
|
+
const spanId = ctx.metadata[SPAN_ID_META_KEY];
|
|
193
|
+
if (spanId) {
|
|
194
|
+
provider.endSpan(spanId, 'error', {
|
|
195
|
+
errorMessage: ctx.error?.message ?? 'unknown',
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// no-op
|
|
201
|
+
}
|
|
202
|
+
return ctx;
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
];
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=telemetry-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-provider.js","sourceRoot":"","sources":["../../../lib/telemetry-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TimelineScrubber — Step through orchestrator history at any sequence point.
|
|
4
|
+
*
|
|
5
|
+
* Wraps an OrchestratorEventBus and reconstructs state at any point by
|
|
6
|
+
* loading the nearest snapshot and replaying events forward. Dashboard
|
|
7
|
+
* clients can "drag a slider" to any sequence and get the state at that
|
|
8
|
+
* moment.
|
|
9
|
+
*
|
|
10
|
+
* @module TimelineScrubber
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.TimelineScrubber = void 0;
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// STATE REDUCER
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/** Apply a single bus event to mutable state. */
|
|
18
|
+
function applyEvent(state, event) {
|
|
19
|
+
switch (event.source) {
|
|
20
|
+
case 'blackboard': {
|
|
21
|
+
if (event.type === 'write' || event.type === 'commit') {
|
|
22
|
+
const key = event.data.key;
|
|
23
|
+
if (key)
|
|
24
|
+
state.blackboard[key] = event.data.value;
|
|
25
|
+
}
|
|
26
|
+
else if (event.type === 'delete') {
|
|
27
|
+
const key = event.data.key;
|
|
28
|
+
if (key)
|
|
29
|
+
delete state.blackboard[key];
|
|
30
|
+
}
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
case 'orchestrator': {
|
|
34
|
+
if (event.type === 'delegation_start' && event.agentId) {
|
|
35
|
+
const target = event.data.targetAgent;
|
|
36
|
+
if (target && !state.agents[target]) {
|
|
37
|
+
state.agents[target] = { status: 'running', tokensUsed: 0 };
|
|
38
|
+
}
|
|
39
|
+
else if (target && state.agents[target]) {
|
|
40
|
+
state.agents[target].status = 'running';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (event.type === 'delegation_failed' && event.data.targetAgent) {
|
|
44
|
+
const target = event.data.targetAgent;
|
|
45
|
+
if (state.agents[target])
|
|
46
|
+
state.agents[target].status = 'failed';
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case 'adapter': {
|
|
51
|
+
if (event.type === 'agent:execution:complete' && event.agentId) {
|
|
52
|
+
if (state.agents[event.agentId]) {
|
|
53
|
+
state.agents[event.agentId].status = 'completed';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
case 'quality': {
|
|
59
|
+
if (event.type === 'reject' && event.agentId) {
|
|
60
|
+
if (state.agents[event.agentId]) {
|
|
61
|
+
state.agents[event.agentId].status = 'failed';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
// Other sources: no state mutation needed for reconstruction
|
|
67
|
+
default:
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// SCRUBBER
|
|
73
|
+
// ============================================================================
|
|
74
|
+
/**
|
|
75
|
+
* Reconstructs state at any point in the event stream.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* const scrubber = new TimelineScrubber(orchestrator.eventBus);
|
|
80
|
+
* const frame = scrubber.frameAt(42);
|
|
81
|
+
* // frame.blackboard — state of blackboard at seq 42
|
|
82
|
+
* // frame.agents — agent statuses at seq 42
|
|
83
|
+
*
|
|
84
|
+
* const range = scrubber.getRange();
|
|
85
|
+
* // range.minSeq, range.maxSeq — slider bounds
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
class TimelineScrubber {
|
|
89
|
+
bus;
|
|
90
|
+
constructor(bus) {
|
|
91
|
+
this.bus = bus;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Reconstruct state at a specific sequence number.
|
|
95
|
+
*/
|
|
96
|
+
frameAt(seq) {
|
|
97
|
+
// Find nearest snapshot at or before seq
|
|
98
|
+
const snapshot = this.bus.snapshotAt(seq);
|
|
99
|
+
// Determine replay start
|
|
100
|
+
const fromSeq = snapshot ? snapshot.atSeq + 1 : 0;
|
|
101
|
+
// Get events from snapshot to target seq
|
|
102
|
+
const replay = this.bus.replay({ fromSeq, toSeq: seq });
|
|
103
|
+
const appliedEvents = replay.events;
|
|
104
|
+
// Initialize state from snapshot or empty
|
|
105
|
+
const blackboard = snapshot
|
|
106
|
+
? { ...snapshot.blackboard }
|
|
107
|
+
: {};
|
|
108
|
+
const agents = snapshot
|
|
109
|
+
? Object.fromEntries(Object.entries(snapshot.agents).map(([k, v]) => [k, { ...v }]))
|
|
110
|
+
: {};
|
|
111
|
+
// Apply events forward
|
|
112
|
+
for (const event of appliedEvents) {
|
|
113
|
+
applyEvent({ blackboard, agents }, event);
|
|
114
|
+
}
|
|
115
|
+
// Find the event timestamp at this seq
|
|
116
|
+
const targetEvent = this.bus.getEvent(seq);
|
|
117
|
+
const timestamp = targetEvent?.timestamp ?? snapshot?.timestamp ?? new Date().toISOString();
|
|
118
|
+
return {
|
|
119
|
+
seq,
|
|
120
|
+
timestamp,
|
|
121
|
+
baseSnapshotSeq: snapshot?.atSeq ?? null,
|
|
122
|
+
appliedEvents,
|
|
123
|
+
blackboard,
|
|
124
|
+
agents,
|
|
125
|
+
budget: snapshot?.budget,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get a range of frames (e.g. for scrubbing a window).
|
|
130
|
+
* Returns frames at evenly-spaced sequence numbers.
|
|
131
|
+
*/
|
|
132
|
+
frameRange(fromSeq, toSeq, maxFrames = 50) {
|
|
133
|
+
const range = toSeq - fromSeq;
|
|
134
|
+
const step = Math.max(1, Math.floor(range / maxFrames));
|
|
135
|
+
const frames = [];
|
|
136
|
+
for (let s = fromSeq; s <= toSeq; s += step) {
|
|
137
|
+
frames.push(this.frameAt(s));
|
|
138
|
+
}
|
|
139
|
+
// Always include the last frame
|
|
140
|
+
if (frames.length === 0 || frames[frames.length - 1].seq !== toSeq) {
|
|
141
|
+
frames.push(this.frameAt(toSeq));
|
|
142
|
+
}
|
|
143
|
+
return frames;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get the timeline range info (slider bounds).
|
|
147
|
+
*/
|
|
148
|
+
getRange() {
|
|
149
|
+
const snapshots = this.bus.getSnapshots();
|
|
150
|
+
const replay = this.bus.replay();
|
|
151
|
+
return {
|
|
152
|
+
minSeq: replay.events.length > 0 ? replay.events[0].seq : 0,
|
|
153
|
+
maxSeq: this.bus.currentSeq - 1,
|
|
154
|
+
totalEvents: replay.totalEvents,
|
|
155
|
+
snapshotCount: snapshots.length,
|
|
156
|
+
snapshotSeqs: snapshots.map(s => s.atSeq),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Step forward from a given frame by N events.
|
|
161
|
+
*/
|
|
162
|
+
stepForward(currentSeq, steps = 1) {
|
|
163
|
+
return this.frameAt(Math.min(currentSeq + steps, this.bus.currentSeq - 1));
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Step backward from a given frame by N events.
|
|
167
|
+
*/
|
|
168
|
+
stepBackward(currentSeq, steps = 1) {
|
|
169
|
+
return this.frameAt(Math.max(currentSeq - steps, 0));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
exports.TimelineScrubber = TimelineScrubber;
|
|
173
|
+
//# sourceMappingURL=timeline-scrubber.js.map
|