@holoscript/framework 6.0.3 → 6.0.4
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/CHANGELOG.md +1 -2
- package/ROADMAP.md +68 -66
- package/dist/{InvisibleWallet-BB6tFvRA.d.cts → InvisibleWallet-EFiuaLn3.d.cts} +1 -1
- package/dist/{OrchestratorAgent-BvWgf9uw.d.cts → OrchestratorAgent-CrLDGNL6.d.cts} +1 -1
- package/dist/agents/index.cjs +11 -10
- package/dist/agents/index.d.cts +4 -16
- package/dist/ai/index.cjs +2 -2
- package/dist/behavior.cjs +10 -0
- package/dist/economy/index.cjs +4 -4
- package/dist/economy/index.d.cts +2 -2
- package/dist/index.cjs +33 -11
- package/dist/index.d.cts +3 -3
- package/dist/swarm/index.cjs +3 -0
- package/package.json +14 -9
- package/src/__tests__/bounty-marketplace.test.ts +53 -21
- package/src/__tests__/delegation.test.ts +1 -4
- package/src/__tests__/done-log-audit.test.ts +38 -46
- package/src/__tests__/framework.test.ts +172 -53
- package/src/__tests__/goal-synthesizer.test.ts +9 -6
- package/src/__tests__/presence.test.ts +1 -1
- package/src/__tests__/protocol-agent.test.ts +12 -11
- package/src/__tests__/revenue-splitter.test.ts +22 -15
- package/src/__tests__/scenario-driven-todo.test.ts +55 -35
- package/src/__tests__/self-improve.test.ts +28 -9
- package/src/__tests__/service-lifecycle.test.ts +9 -3
- package/src/__tests__/skill-router.test.ts +3 -3
- package/src/agents/CulturalMemory.ts +6 -6
- package/src/agents/DelegationTraceHooks.ts +560 -0
- package/src/agents/FederatedRegistryAdapter.ts +1 -1
- package/src/agents/NormEngine.ts +3 -8
- package/src/agents/OrchestratorAgent.ts +1 -1
- package/src/agents/TaskDelegationService.ts +5 -9
- package/src/agents/__tests__/AgentWalletRegistry.test.ts +5 -4
- package/src/agents/__tests__/CrossRealityHandoff.test.ts +9 -3
- package/src/agents/__tests__/DelegationTraceHooks.test.ts +390 -0
- package/src/agents/__tests__/TaskDelegationService.test.ts +4 -2
- package/src/agents/spatial-comms/Layer1RealTime.ts +36 -19
- package/src/agents/spatial-comms/Layer2A2A.ts +1 -3
- package/src/agents/spatial-comms/Layer3MCP.ts +13 -4
- package/src/agents/spatial-comms/ProtocolTypes.ts +5 -2
- package/src/agents/spatial-comms/examples/multi-agent-world-creation.ts +2 -2
- package/src/ai/HoloScriptGenerator.ts +2 -2
- package/src/ai/__tests__/PerceptionSystem.prod.test.ts +1 -1
- package/src/ai/__tests__/PerceptionSystem.test.ts +14 -14
- package/src/ai/__tests__/SteeringBehaviors.prod.test.ts +1 -1
- package/src/ai/index.ts +5 -1
- package/src/board/audit.ts +17 -6
- package/src/board/board-ops.ts +45 -15
- package/src/board/board-types.ts +94 -20
- package/src/delegation.ts +5 -3
- package/src/distributed-claimer.ts +13 -2
- package/src/economy/BountyManager.ts +40 -18
- package/src/economy/KnowledgeMarketplace.ts +27 -8
- package/src/economy/PaymentWebhookService.ts +0 -1
- package/src/economy/RevenueSplitter.ts +2 -4
- package/src/economy/UnifiedBudgetOptimizer.ts +8 -9
- package/src/economy/_core-stubs.ts +1 -1
- package/src/economy/x402-facilitator.ts +17 -8
- package/src/index.ts +16 -12
- package/src/knowledge/__tests__/knowledge-consolidator.test.ts +138 -89
- package/src/knowledge/__tests__/knowledge-store-vector.test.ts +59 -16
- package/src/knowledge/brain.ts +7 -7
- package/src/knowledge/consolidation.ts +16 -16
- package/src/knowledge/knowledge-consolidator.ts +60 -30
- package/src/knowledge/knowledge-store.ts +83 -45
- package/src/learning/ProceduralCompiler.ts +6 -1
- package/src/learning/learning/MemoryConsolidator.ts +102 -0
- package/src/learning/learning/MemoryScorer.ts +69 -0
- package/src/learning/learning/ProceduralCompiler.ts +45 -0
- package/src/learning/learning/SemanticClusterer.ts +66 -0
- package/src/llm/llm-adapter.ts +24 -10
- package/src/mesh/index.ts +37 -17
- package/src/protocol/goal-synthesizer.ts +24 -34
- package/src/protocol/implementations.ts +91 -22
- package/src/protocol/micro-phase-decomposer.ts +25 -17
- package/src/protocol/micro-step-decomposer.test.ts +104 -39
- package/src/protocol-agent.test.ts +17 -7
- package/src/protocol-agent.ts +45 -42
- package/src/self-improve/absorb-scanner.ts +9 -6
- package/src/self-improve/evolution-engine.ts +36 -18
- package/src/self-improve/framework-absorber.ts +21 -16
- package/src/self-improve/index.ts +2 -10
- package/src/self-improve/prompt-optimizer.ts +31 -19
- package/src/self-improve/test-generator.ts +16 -12
- package/src/skill-router.ts +7 -6
- package/src/swarm/messaging/GossipProtocol.ts +1 -1
- package/src/swarm/messaging/__tests__/BroadcastChannel.prod.test.ts +31 -9
- package/src/swarm/messaging/__tests__/GossipProtocol.prod.test.ts +21 -7
- package/src/swarm/messaging/__tests__/SwarmEventBus.prod.test.ts +24 -8
- package/src/swarm/messaging/__tests__/SwarmEventBus.test.ts +6 -2
- package/src/team.ts +277 -122
- package/src/training/scripts/generate-spatial-dataset.ts +1 -1
- package/src/training/training/LRScheduler.ts +377 -0
- package/src/training/training/QualityScoringPipeline.ts +139 -0
- package/src/training/training/SoftDedup.ts +461 -0
- package/src/training/training/SparsityMonitor.ts +685 -0
- package/src/training/training/SparsityMonitorTypes.ts +209 -0
- package/src/training/training/SpatialTrainingDataGenerator.ts +1526 -0
- package/src/training/training/SpatialTrainingDataTypes.ts +216 -0
- package/src/training/training/TrainingPipelineConfig.ts +215 -0
- package/src/training/training/__tests__/CorpusValidation.test.ts +87 -0
- package/src/training/training/__tests__/LRScheduler.test.ts +592 -0
- package/src/training/training/__tests__/SoftDedup.test.ts +415 -0
- package/src/training/training/__tests__/SparsityMonitor.test.ts +1623 -0
- package/src/training/training/__tests__/SpatialCorpusValidation.test.ts +72 -0
- package/src/training/training/__tests__/SpatialTrainingDataGenerator.test.ts +1244 -0
- package/src/training/training/__tests__/TrainingMonkeyIntegration.test.ts +897 -0
- package/src/training/training/__tests__/TrainingPipelineConfig.test.ts +202 -0
- package/src/training/training/__tests__/schema.test.ts +72 -0
- package/src/training/training/__tests__/training-constants.test.ts +106 -0
- package/src/training/training/__tests__/trait-mappings.test.ts +81 -0
- package/src/training/training/constants.ts +94 -0
- package/src/training/training/index.ts +17 -0
- package/src/training/training/schema.ts +147 -0
- package/src/training/training/scripts/generate-novel-use-cases-dataset.ts +272 -0
- package/src/training/training/scripts/generate-spatial-dataset.ts +521 -0
- package/src/training/training/trainingmonkey/TrainingMonkeyIntegration.ts +477 -0
- package/src/training/training/trainingmonkey/TrainingMonkeyTypes.ts +230 -0
- package/src/training/training/trainingmonkey/index.ts +26 -0
- package/src/training/training/trait-mappings.ts +157 -0
- package/src/types.ts +2 -7
- package/ALL-test-results.json +0 -1
- package/LICENSE +0 -21
- package/dist/AgentManifest-CB4xM-Ma.d.ts +0 -704
- package/dist/BehaviorTree-BrBFECv5.d.ts +0 -103
- package/dist/InvisibleWallet-rtRrBOA8.d.ts +0 -1732
- package/dist/OrchestratorAgent-Q_CbVTmO.d.ts +0 -798
- package/dist/agents/index.d.ts +0 -1788
- package/dist/agents/index.js +0 -4695
- package/dist/ai/index.d.ts +0 -1753
- package/dist/ai/index.js +0 -5244
- package/dist/behavior.d.ts +0 -130
- package/dist/behavior.js +0 -407
- package/dist/economy/index.d.ts +0 -747
- package/dist/economy/index.js +0 -3617
- package/dist/implementations-D9T3un9D.d.ts +0 -236
- package/dist/index.d.ts +0 -1729
- package/dist/index.js +0 -24277
- package/dist/learning/index.d.ts +0 -104
- package/dist/learning/index.js +0 -189
- package/dist/negotiation/index.d.ts +0 -610
- package/dist/negotiation/index.js +0 -931
- package/dist/skills/index.d.ts +0 -289
- package/dist/skills/index.js +0 -1079
- package/dist/swarm/index.d.ts +0 -2433
- package/dist/swarm/index.js +0 -5221
- package/dist/training/index.d.ts +0 -1734
- package/dist/training/index.js +0 -2687
- package/extract-failures.js +0 -10
- package/src/training/training/data/novel-use-cases.jsonl +0 -153
- package/src/training/training/data/spatial-reasoning-10k.jsonl +0 -9354
- package/src/types/core-stubs.d.ts +0 -113
- package/test-output.txt +0 -0
- package/test-result.json +0 -1
- package/tsc-errors.txt +0 -4
- package/tsc_output.txt +0 -0
- package/typescript-errors-2.txt +0 -0
- package/typescript-errors.txt +0 -22
- package/vitest-log-utf8.txt +0 -268
- package/vitest-log.txt +0 -0
|
@@ -19,11 +19,7 @@ export {
|
|
|
19
19
|
scanTodos,
|
|
20
20
|
} from './absorb-scanner';
|
|
21
21
|
|
|
22
|
-
export {
|
|
23
|
-
type EvolutionConfig,
|
|
24
|
-
type EvolutionResult,
|
|
25
|
-
evolve,
|
|
26
|
-
} from './evolution-engine';
|
|
22
|
+
export { type EvolutionConfig, type EvolutionResult, evolve } from './evolution-engine';
|
|
27
23
|
|
|
28
24
|
// FW-1.0: Class-based absorb integration
|
|
29
25
|
export {
|
|
@@ -34,11 +30,7 @@ export {
|
|
|
34
30
|
} from './framework-absorber';
|
|
35
31
|
|
|
36
32
|
// FW-1.0: Auto-test generation via LLM
|
|
37
|
-
export {
|
|
38
|
-
TestGenerator,
|
|
39
|
-
type TestGeneratorConfig,
|
|
40
|
-
type GeneratedTest,
|
|
41
|
-
} from './test-generator';
|
|
33
|
+
export { TestGenerator, type TestGeneratorConfig, type GeneratedTest } from './test-generator';
|
|
42
34
|
|
|
43
35
|
// FW-1.0: Prompt optimization via A/B testing
|
|
44
36
|
export {
|
|
@@ -126,7 +126,11 @@ export class PromptOptimizer {
|
|
|
126
126
|
/**
|
|
127
127
|
* Run a single variant N times and evaluate.
|
|
128
128
|
*/
|
|
129
|
-
private async runVariant(
|
|
129
|
+
private async runVariant(
|
|
130
|
+
prompt: string,
|
|
131
|
+
task: string,
|
|
132
|
+
runs: number
|
|
133
|
+
): Promise<PromptVariantResult> {
|
|
130
134
|
const responses: string[] = [];
|
|
131
135
|
const scores: number[] = [];
|
|
132
136
|
let totalTokens = 0;
|
|
@@ -134,13 +138,17 @@ export class PromptOptimizer {
|
|
|
134
138
|
|
|
135
139
|
for (let i = 0; i < runs; i++) {
|
|
136
140
|
const start = Date.now();
|
|
137
|
-
const response = await callLLM(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
const response = await callLLM(
|
|
142
|
+
this.config.model,
|
|
143
|
+
[
|
|
144
|
+
{ role: 'system', content: prompt },
|
|
145
|
+
{ role: 'user', content: task },
|
|
146
|
+
],
|
|
147
|
+
{
|
|
148
|
+
maxTokens: this.config.maxTokens,
|
|
149
|
+
temperature: this.config.temperature,
|
|
150
|
+
}
|
|
151
|
+
);
|
|
144
152
|
const latency = Date.now() - start;
|
|
145
153
|
|
|
146
154
|
responses.push(response.content);
|
|
@@ -170,17 +178,21 @@ export class PromptOptimizer {
|
|
|
170
178
|
const criteria = this.config.criteria!;
|
|
171
179
|
|
|
172
180
|
try {
|
|
173
|
-
const judgeResponse = await callLLM(
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
role: '
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
181
|
+
const judgeResponse = await callLLM(
|
|
182
|
+
this.config.model,
|
|
183
|
+
[
|
|
184
|
+
{ role: 'system', content: JUDGE_SYSTEM },
|
|
185
|
+
{
|
|
186
|
+
role: 'user',
|
|
187
|
+
content: [
|
|
188
|
+
`Task: ${task}`,
|
|
189
|
+
`Response: ${response}`,
|
|
190
|
+
`Criteria: ${criteria.map((c) => `${c.name} (${c.description})`).join(', ')}`,
|
|
191
|
+
].join('\n'),
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
{ maxTokens: 200, temperature: 0 }
|
|
195
|
+
);
|
|
184
196
|
|
|
185
197
|
const parsed = JSON.parse(judgeResponse.content) as Record<string, number>;
|
|
186
198
|
let weightedSum = 0;
|
|
@@ -52,7 +52,7 @@ Use import { describe, it, expect, vi } from 'vitest';`;
|
|
|
52
52
|
|
|
53
53
|
const JEST_SYSTEM_PROMPT = SYSTEM_PROMPT.replace(
|
|
54
54
|
"import { describe, it, expect, vi } from 'vitest';",
|
|
55
|
-
|
|
55
|
+
'Use jest globals (describe, it, expect, jest).'
|
|
56
56
|
);
|
|
57
57
|
|
|
58
58
|
/**
|
|
@@ -95,9 +95,7 @@ export class TestGenerator {
|
|
|
95
95
|
const fileName = basename(absPath, '.ts');
|
|
96
96
|
const dir = dirname(absPath);
|
|
97
97
|
|
|
98
|
-
const systemPrompt = this.config.testFramework === 'jest'
|
|
99
|
-
? JEST_SYSTEM_PROMPT
|
|
100
|
-
: SYSTEM_PROMPT;
|
|
98
|
+
const systemPrompt = this.config.testFramework === 'jest' ? JEST_SYSTEM_PROMPT : SYSTEM_PROMPT;
|
|
101
99
|
|
|
102
100
|
const userPrompt = [
|
|
103
101
|
`Generate tests for this TypeScript file: ${basename(absPath)}`,
|
|
@@ -105,16 +103,22 @@ export class TestGenerator {
|
|
|
105
103
|
'```typescript',
|
|
106
104
|
source,
|
|
107
105
|
'```',
|
|
108
|
-
this.config.additionalContext
|
|
106
|
+
this.config.additionalContext
|
|
107
|
+
? `\nAdditional context:\n${this.config.additionalContext}`
|
|
108
|
+
: '',
|
|
109
109
|
].join('\n');
|
|
110
110
|
|
|
111
|
-
const response = await callLLM(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
const response = await callLLM(
|
|
112
|
+
this.config.model,
|
|
113
|
+
[
|
|
114
|
+
{ role: 'system', content: systemPrompt },
|
|
115
|
+
{ role: 'user', content: userPrompt },
|
|
116
|
+
],
|
|
117
|
+
{
|
|
118
|
+
maxTokens: this.config.maxTokens,
|
|
119
|
+
temperature: this.config.temperature,
|
|
120
|
+
}
|
|
121
|
+
);
|
|
118
122
|
|
|
119
123
|
const testContent = cleanTestOutput(response.content);
|
|
120
124
|
const testCount = countTestCases(testContent);
|
package/src/skill-router.ts
CHANGED
|
@@ -84,9 +84,9 @@ export class SkillRouter {
|
|
|
84
84
|
|
|
85
85
|
for (const agent of agents) {
|
|
86
86
|
// Check required capabilities
|
|
87
|
-
const agentCaps = new Set(agent.capabilities.map(c => c.toLowerCase()));
|
|
87
|
+
const agentCaps = new Set(agent.capabilities.map((c) => c.toLowerCase()));
|
|
88
88
|
if (p.requiredCapabilities.length > 0) {
|
|
89
|
-
const hasAll = p.requiredCapabilities.every(rc => agentCaps.has(rc.toLowerCase()));
|
|
89
|
+
const hasAll = p.requiredCapabilities.every((rc) => agentCaps.has(rc.toLowerCase()));
|
|
90
90
|
if (!hasAll) continue;
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -128,16 +128,17 @@ export class SkillRouter {
|
|
|
128
128
|
candidates.sort((a, b) => b.score - a.score);
|
|
129
129
|
|
|
130
130
|
// Apply minimum threshold
|
|
131
|
-
const eligible = candidates.filter(c => c.score >= p.minScore);
|
|
131
|
+
const eligible = candidates.filter((c) => c.score >= p.minScore);
|
|
132
132
|
|
|
133
133
|
if (eligible.length === 0) {
|
|
134
134
|
return {
|
|
135
135
|
agent: null,
|
|
136
136
|
score: 0,
|
|
137
137
|
candidates,
|
|
138
|
-
reason:
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
reason:
|
|
139
|
+
candidates.length > 0
|
|
140
|
+
? `${candidates.length} candidates scored below minimum threshold (${p.minScore})`
|
|
141
|
+
: 'No candidates matched task requirements',
|
|
141
142
|
};
|
|
142
143
|
}
|
|
143
144
|
|
|
@@ -78,7 +78,9 @@ describe('BroadcastChannel — broadcast', () => {
|
|
|
78
78
|
it('delivers to subscriber', async () => {
|
|
79
79
|
const received: unknown[] = [];
|
|
80
80
|
const c = makeCh();
|
|
81
|
-
c.subscribe('a1', (m) => {
|
|
81
|
+
c.subscribe('a1', (m) => {
|
|
82
|
+
received.push((m as any).content);
|
|
83
|
+
});
|
|
82
84
|
await c.broadcast('sender', 'hello');
|
|
83
85
|
expect(received).toHaveLength(1);
|
|
84
86
|
expect(received[0]).toBe('hello');
|
|
@@ -86,15 +88,25 @@ describe('BroadcastChannel — broadcast', () => {
|
|
|
86
88
|
it('delivered to all subscribers', async () => {
|
|
87
89
|
const received: unknown[] = [];
|
|
88
90
|
const c = makeCh();
|
|
89
|
-
c.subscribe('a1', (m) => {
|
|
90
|
-
|
|
91
|
+
c.subscribe('a1', (m) => {
|
|
92
|
+
received.push(m);
|
|
93
|
+
});
|
|
94
|
+
c.subscribe('a2', (m) => {
|
|
95
|
+
received.push(m);
|
|
96
|
+
});
|
|
91
97
|
await c.broadcast('sender', 'hi');
|
|
92
98
|
expect(received).toHaveLength(2);
|
|
93
99
|
});
|
|
94
100
|
it('publisher-role subscriber does not receive', async () => {
|
|
95
101
|
const received: unknown[] = [];
|
|
96
102
|
const c = makeCh();
|
|
97
|
-
c.subscribe(
|
|
103
|
+
c.subscribe(
|
|
104
|
+
'a1',
|
|
105
|
+
(m) => {
|
|
106
|
+
received.push('a1', m);
|
|
107
|
+
},
|
|
108
|
+
{ role: 'publisher' }
|
|
109
|
+
);
|
|
98
110
|
await c.broadcast('sender', 'hi');
|
|
99
111
|
expect(received).toHaveLength(0);
|
|
100
112
|
});
|
|
@@ -122,8 +134,12 @@ describe('BroadcastChannel — sendDirect', () => {
|
|
|
122
134
|
it('delivers only to target', async () => {
|
|
123
135
|
const received: string[] = [];
|
|
124
136
|
const c = makeCh();
|
|
125
|
-
c.subscribe('a1', () => {
|
|
126
|
-
|
|
137
|
+
c.subscribe('a1', () => {
|
|
138
|
+
received.push('a1');
|
|
139
|
+
});
|
|
140
|
+
c.subscribe('a2', () => {
|
|
141
|
+
received.push('a2');
|
|
142
|
+
});
|
|
127
143
|
await c.sendDirect('sender', 'a1', 'dm');
|
|
128
144
|
expect(received).toHaveLength(1);
|
|
129
145
|
expect(received[0]).toBe('a1');
|
|
@@ -213,7 +229,9 @@ describe('BroadcastChannel — replayHistory', () => {
|
|
|
213
229
|
const c = makeCh();
|
|
214
230
|
await c.broadcast('s', '1');
|
|
215
231
|
await c.broadcast('s', '2');
|
|
216
|
-
const subId = c.subscribe('a1', (m) => {
|
|
232
|
+
const subId = c.subscribe('a1', (m) => {
|
|
233
|
+
received.push(m);
|
|
234
|
+
});
|
|
217
235
|
const count = await c.replayHistory(subId);
|
|
218
236
|
expect(count).toBe(2);
|
|
219
237
|
expect(received).toHaveLength(2);
|
|
@@ -316,8 +334,12 @@ describe('ChannelManager — multicast', () => {
|
|
|
316
334
|
const c1 = m.createChannel('c1');
|
|
317
335
|
const c2 = m.createChannel('c2');
|
|
318
336
|
const received: string[] = [];
|
|
319
|
-
m.subscribeAgent('a1', c1.id, () => {
|
|
320
|
-
|
|
337
|
+
m.subscribeAgent('a1', c1.id, () => {
|
|
338
|
+
received.push('c1');
|
|
339
|
+
});
|
|
340
|
+
m.subscribeAgent('a2', c2.id, () => {
|
|
341
|
+
received.push('c2');
|
|
342
|
+
});
|
|
321
343
|
const results = await m.multicast([c1.id, c2.id], 'sender', 'msg');
|
|
322
344
|
expect(results.size).toBe(2);
|
|
323
345
|
expect(received).toHaveLength(2);
|
|
@@ -127,7 +127,9 @@ describe('GossipProtocol — publish', () => {
|
|
|
127
127
|
it('publish calls type-specific handler synchronously', () => {
|
|
128
128
|
const n = mkNode();
|
|
129
129
|
const received: IGossipMessage[] = [];
|
|
130
|
-
n.subscribe('data', (msg) => {
|
|
130
|
+
n.subscribe('data', (msg) => {
|
|
131
|
+
received.push(msg);
|
|
132
|
+
});
|
|
131
133
|
n.publish({ v: 42 }, 'data');
|
|
132
134
|
expect(received).toHaveLength(1);
|
|
133
135
|
expect((received[0].content as any).v).toBe(42);
|
|
@@ -135,21 +137,27 @@ describe('GossipProtocol — publish', () => {
|
|
|
135
137
|
it('publish calls wildcard handler', () => {
|
|
136
138
|
const n = mkNode();
|
|
137
139
|
const received: IGossipMessage[] = [];
|
|
138
|
-
n.subscribe('*', (msg) => {
|
|
140
|
+
n.subscribe('*', (msg) => {
|
|
141
|
+
received.push(msg);
|
|
142
|
+
});
|
|
139
143
|
n.publish({ v: 1 }, 'heartbeat');
|
|
140
144
|
expect(received).toHaveLength(1);
|
|
141
145
|
});
|
|
142
146
|
it('publishHeartbeat uses type=heartbeat', () => {
|
|
143
147
|
const n = mkNode();
|
|
144
148
|
const received: IGossipMessage[] = [];
|
|
145
|
-
n.subscribe('heartbeat', (msg) => {
|
|
149
|
+
n.subscribe('heartbeat', (msg) => {
|
|
150
|
+
received.push(msg);
|
|
151
|
+
});
|
|
146
152
|
n.publishHeartbeat();
|
|
147
153
|
expect(received).toHaveLength(1);
|
|
148
154
|
});
|
|
149
155
|
it('publishMembership uses type=membership', () => {
|
|
150
156
|
const n = mkNode();
|
|
151
157
|
const received: IGossipMessage[] = [];
|
|
152
|
-
n.subscribe('membership', (msg) => {
|
|
158
|
+
n.subscribe('membership', (msg) => {
|
|
159
|
+
received.push(msg);
|
|
160
|
+
});
|
|
153
161
|
n.publishMembership('join');
|
|
154
162
|
expect(received).toHaveLength(1);
|
|
155
163
|
});
|
|
@@ -189,7 +197,9 @@ describe('GossipProtocol — receive', () => {
|
|
|
189
197
|
it('receive calls handler', async () => {
|
|
190
198
|
const n = mkNode();
|
|
191
199
|
const received: any[] = [];
|
|
192
|
-
n.subscribe('data', (msg) => {
|
|
200
|
+
n.subscribe('data', (msg) => {
|
|
201
|
+
received.push(msg);
|
|
202
|
+
});
|
|
193
203
|
await n.receive(mkMsg({ type: 'data' }), 'peer');
|
|
194
204
|
expect(received).toHaveLength(1);
|
|
195
205
|
});
|
|
@@ -218,7 +228,9 @@ describe('GossipProtocol — subscribe / unsubscribe', () => {
|
|
|
218
228
|
it('unsubscribe stops future deliveries', () => {
|
|
219
229
|
const n = mkNode();
|
|
220
230
|
const calls: number[] = [];
|
|
221
|
-
const unsub = n.subscribe('data', () => {
|
|
231
|
+
const unsub = n.subscribe('data', () => {
|
|
232
|
+
calls.push(1);
|
|
233
|
+
});
|
|
222
234
|
n.publish({ x: 1 }, 'data');
|
|
223
235
|
unsub();
|
|
224
236
|
n.publish({ x: 2 }, 'data');
|
|
@@ -227,7 +239,9 @@ describe('GossipProtocol — subscribe / unsubscribe', () => {
|
|
|
227
239
|
it('wildcard receives all message types', async () => {
|
|
228
240
|
const n = mkNode();
|
|
229
241
|
const types: string[] = [];
|
|
230
|
-
n.subscribe('*', (msg) => {
|
|
242
|
+
n.subscribe('*', (msg) => {
|
|
243
|
+
types.push(msg.type);
|
|
244
|
+
});
|
|
231
245
|
n.publish({}, 'data');
|
|
232
246
|
n.publish({}, 'heartbeat');
|
|
233
247
|
n.publish({}, 'membership');
|
|
@@ -82,7 +82,9 @@ describe('SwarmEventBus — emit (synchronous)', () => {
|
|
|
82
82
|
it('delivers synchronously to matching subscriber', () => {
|
|
83
83
|
let received: unknown[] = [];
|
|
84
84
|
const bus = make();
|
|
85
|
-
bus.subscribe('evt.ping', (e) => {
|
|
85
|
+
bus.subscribe('evt.ping', (e) => {
|
|
86
|
+
received.push(e.payload);
|
|
87
|
+
});
|
|
86
88
|
bus.emit('evt.ping', 'src', { val: 42 });
|
|
87
89
|
expect(received).toHaveLength(1);
|
|
88
90
|
expect((received[0] as any).val).toBe(42);
|
|
@@ -90,14 +92,18 @@ describe('SwarmEventBus — emit (synchronous)', () => {
|
|
|
90
92
|
it('does not deliver to non-matching subscriber', () => {
|
|
91
93
|
let received: unknown[] = [];
|
|
92
94
|
const bus = make();
|
|
93
|
-
bus.subscribe('other', (e) => {
|
|
95
|
+
bus.subscribe('other', (e) => {
|
|
96
|
+
received.push(e.payload);
|
|
97
|
+
});
|
|
94
98
|
bus.emit('evt.ping', 'src', {});
|
|
95
99
|
expect(received).toHaveLength(0);
|
|
96
100
|
});
|
|
97
101
|
it('wildcard pattern matches', () => {
|
|
98
102
|
let received: unknown[] = [];
|
|
99
103
|
const bus = make();
|
|
100
|
-
bus.subscribe('swarm.*', (e) => {
|
|
104
|
+
bus.subscribe('swarm.*', (e) => {
|
|
105
|
+
received.push(e.payload);
|
|
106
|
+
});
|
|
101
107
|
bus.emit('swarm.joined', 'src', {});
|
|
102
108
|
bus.emit('swarm.left', 'src', {});
|
|
103
109
|
expect(received).toHaveLength(2);
|
|
@@ -105,7 +111,9 @@ describe('SwarmEventBus — emit (synchronous)', () => {
|
|
|
105
111
|
it('regex pattern matches', () => {
|
|
106
112
|
let received: unknown[] = [];
|
|
107
113
|
const bus = make();
|
|
108
|
-
bus.subscribe(/^agent\./, (e) => {
|
|
114
|
+
bus.subscribe(/^agent\./, (e) => {
|
|
115
|
+
received.push(e.payload);
|
|
116
|
+
});
|
|
109
117
|
bus.emit('agent.spawn', 'src', {});
|
|
110
118
|
bus.emit('agent.destroy', 'src', {});
|
|
111
119
|
bus.emit('other.event', 'src', {});
|
|
@@ -114,7 +122,9 @@ describe('SwarmEventBus — emit (synchronous)', () => {
|
|
|
114
122
|
it('exact match only', () => {
|
|
115
123
|
let received: unknown[] = [];
|
|
116
124
|
const bus = make();
|
|
117
|
-
bus.subscribe('exact', (e) => {
|
|
125
|
+
bus.subscribe('exact', (e) => {
|
|
126
|
+
received.push(e.payload);
|
|
127
|
+
});
|
|
118
128
|
bus.emit('exact.extended', 'src', {});
|
|
119
129
|
expect(received).toHaveLength(0);
|
|
120
130
|
});
|
|
@@ -124,7 +134,9 @@ describe('SwarmEventBus — processQueue', () => {
|
|
|
124
134
|
it('delivers events to subscribers', async () => {
|
|
125
135
|
let received: unknown[] = [];
|
|
126
136
|
const bus = make({ asyncProcessing: false });
|
|
127
|
-
bus.subscribe('greet', (e) => {
|
|
137
|
+
bus.subscribe('greet', (e) => {
|
|
138
|
+
received.push(e.payload);
|
|
139
|
+
});
|
|
128
140
|
bus.publish('greet', 'src', 'hello');
|
|
129
141
|
await bus.processQueue();
|
|
130
142
|
expect(received).toHaveLength(1);
|
|
@@ -132,7 +144,9 @@ describe('SwarmEventBus — processQueue', () => {
|
|
|
132
144
|
it('skips expired TTL events', async () => {
|
|
133
145
|
let received: unknown[] = [];
|
|
134
146
|
const bus = make({ asyncProcessing: false, defaultTTL: 1 });
|
|
135
|
-
bus.subscribe('late', (e) => {
|
|
147
|
+
bus.subscribe('late', (e) => {
|
|
148
|
+
received.push(e.payload);
|
|
149
|
+
});
|
|
136
150
|
bus.publish('late', 'src', {}, { ttl: 1 });
|
|
137
151
|
await new Promise((r) => setTimeout(r, 5)); // let TTL expire
|
|
138
152
|
await bus.processQueue();
|
|
@@ -168,7 +182,9 @@ describe('SwarmEventBus — dead letter / replay', () => {
|
|
|
168
182
|
const bus = make({ asyncProcessing: false });
|
|
169
183
|
bus.publish('retry', 'src', 'payload');
|
|
170
184
|
await bus.processQueue(); // to DLQ
|
|
171
|
-
bus.subscribe('retry', (e) => {
|
|
185
|
+
bus.subscribe('retry', (e) => {
|
|
186
|
+
received.push(e.payload);
|
|
187
|
+
});
|
|
172
188
|
bus.replayDeadLetters();
|
|
173
189
|
await bus.processQueue();
|
|
174
190
|
expect(received).toContain('payload');
|
|
@@ -102,11 +102,15 @@ describe('SwarmEventBus', () => {
|
|
|
102
102
|
it('should process critical events by priority order', async () => {
|
|
103
103
|
const order: string[] = [];
|
|
104
104
|
|
|
105
|
-
bus.subscribe('event', (e: any) => {
|
|
105
|
+
bus.subscribe('event', (e: any) => {
|
|
106
|
+
order.push(e.priority);
|
|
107
|
+
});
|
|
106
108
|
|
|
107
109
|
// Use publish with asyncProcessing: false - events are queued by priority
|
|
108
110
|
const asyncBus = new SwarmEventBus({ asyncProcessing: true });
|
|
109
|
-
asyncBus.subscribe('event', (e: any) => {
|
|
111
|
+
asyncBus.subscribe('event', (e: any) => {
|
|
112
|
+
order.push(e.priority);
|
|
113
|
+
});
|
|
110
114
|
|
|
111
115
|
// Emit directly for synchronous test
|
|
112
116
|
bus.emit('event', 'a', {}, { priority: 'low' });
|