@holoscript/framework 6.0.3
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/ALL-test-results.json +1 -0
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/ROADMAP.md +175 -0
- package/dist/AgentManifest-CB4xM-Ma.d.cts +704 -0
- package/dist/AgentManifest-CB4xM-Ma.d.ts +704 -0
- package/dist/BehaviorTree-BrBFECv5.d.cts +103 -0
- package/dist/BehaviorTree-BrBFECv5.d.ts +103 -0
- package/dist/InvisibleWallet-BB6tFvRA.d.cts +1732 -0
- package/dist/InvisibleWallet-rtRrBOA8.d.ts +1732 -0
- package/dist/OrchestratorAgent-BvWgf9uw.d.cts +798 -0
- package/dist/OrchestratorAgent-Q_CbVTmO.d.ts +798 -0
- package/dist/agents/index.cjs +4790 -0
- package/dist/agents/index.d.cts +1788 -0
- package/dist/agents/index.d.ts +1788 -0
- package/dist/agents/index.js +4695 -0
- package/dist/ai/index.cjs +5347 -0
- package/dist/ai/index.d.cts +1753 -0
- package/dist/ai/index.d.ts +1753 -0
- package/dist/ai/index.js +5244 -0
- package/dist/behavior.cjs +449 -0
- package/dist/behavior.d.cts +130 -0
- package/dist/behavior.d.ts +130 -0
- package/dist/behavior.js +407 -0
- package/dist/economy/index.cjs +3659 -0
- package/dist/economy/index.d.cts +747 -0
- package/dist/economy/index.d.ts +747 -0
- package/dist/economy/index.js +3617 -0
- package/dist/implementations-D9T3un9D.d.cts +236 -0
- package/dist/implementations-D9T3un9D.d.ts +236 -0
- package/dist/index.cjs +24550 -0
- package/dist/index.d.cts +1729 -0
- package/dist/index.d.ts +1729 -0
- package/dist/index.js +24277 -0
- package/dist/learning/index.cjs +219 -0
- package/dist/learning/index.d.cts +104 -0
- package/dist/learning/index.d.ts +104 -0
- package/dist/learning/index.js +189 -0
- package/dist/negotiation/index.cjs +970 -0
- package/dist/negotiation/index.d.cts +610 -0
- package/dist/negotiation/index.d.ts +610 -0
- package/dist/negotiation/index.js +931 -0
- package/dist/skills/index.cjs +1118 -0
- package/dist/skills/index.d.cts +289 -0
- package/dist/skills/index.d.ts +289 -0
- package/dist/skills/index.js +1079 -0
- package/dist/swarm/index.cjs +5268 -0
- package/dist/swarm/index.d.cts +2433 -0
- package/dist/swarm/index.d.ts +2433 -0
- package/dist/swarm/index.js +5221 -0
- package/dist/training/index.cjs +2745 -0
- package/dist/training/index.d.cts +1734 -0
- package/dist/training/index.d.ts +1734 -0
- package/dist/training/index.js +2687 -0
- package/extract-failures.js +10 -0
- package/package.json +82 -0
- package/src/__tests__/bounty-marketplace.test.ts +374 -0
- package/src/__tests__/delegation.test.ts +144 -0
- package/src/__tests__/distributed-claimer.test.ts +147 -0
- package/src/__tests__/done-log-audit.test.ts +342 -0
- package/src/__tests__/framework.test.ts +865 -0
- package/src/__tests__/goal-synthesizer.test.ts +236 -0
- package/src/__tests__/presence.test.ts +223 -0
- package/src/__tests__/protocol-agent.test.ts +254 -0
- package/src/__tests__/revenue-splitter.test.ts +114 -0
- package/src/__tests__/scenario-driven-todo.test.ts +197 -0
- package/src/__tests__/self-improve.test.ts +349 -0
- package/src/__tests__/service-lifecycle.test.ts +237 -0
- package/src/__tests__/skill-router.test.ts +121 -0
- package/src/agents/AgentManifest.ts +493 -0
- package/src/agents/AgentRegistry.ts +475 -0
- package/src/agents/AgentTypes.ts +585 -0
- package/src/agents/AgentWalletRegistry.ts +83 -0
- package/src/agents/AuthenticatedCRDT.ts +388 -0
- package/src/agents/CapabilityMatcher.ts +453 -0
- package/src/agents/CrossRealityHandoff.ts +305 -0
- package/src/agents/CulturalMemory.ts +454 -0
- package/src/agents/FederatedRegistryAdapter.ts +429 -0
- package/src/agents/NormEngine.ts +450 -0
- package/src/agents/OrchestratorAgent.ts +414 -0
- package/src/agents/SkillWorkflowEngine.ts +472 -0
- package/src/agents/TaskDelegationService.ts +551 -0
- package/src/agents/__tests__/AgentManifest.prod.test.ts +134 -0
- package/src/agents/__tests__/AgentManifest.test.ts +182 -0
- package/src/agents/__tests__/AgentModule.test.ts +864 -0
- package/src/agents/__tests__/AgentRegistry.prod.test.ts +125 -0
- package/src/agents/__tests__/AgentRegistry.test.ts +148 -0
- package/src/agents/__tests__/AgentTypes.test.ts +534 -0
- package/src/agents/__tests__/AgentWalletRegistry.test.ts +152 -0
- package/src/agents/__tests__/AuthenticatedCRDT.test.ts +558 -0
- package/src/agents/__tests__/CapabilityMatcher.prod.test.ts +117 -0
- package/src/agents/__tests__/CapabilityMatcher.test.ts +178 -0
- package/src/agents/__tests__/CrossRealityHandoff.test.ts +402 -0
- package/src/agents/__tests__/CulturalMemory.test.ts +200 -0
- package/src/agents/__tests__/FederatedRegistryAdapter.test.ts +409 -0
- package/src/agents/__tests__/NormEngine.test.ts +276 -0
- package/src/agents/__tests__/OrchestratorAgent.test.ts +182 -0
- package/src/agents/__tests__/SkillWorkflowEngine.test.ts +357 -0
- package/src/agents/__tests__/TaskDelegationService.test.ts +446 -0
- package/src/agents/index.ts +107 -0
- package/src/agents/spatial-comms/Layer1RealTime.ts +621 -0
- package/src/agents/spatial-comms/Layer2A2A.ts +661 -0
- package/src/agents/spatial-comms/Layer3MCP.ts +651 -0
- package/src/agents/spatial-comms/ProtocolTypes.ts +543 -0
- package/src/agents/spatial-comms/SpatialCommClient.ts +483 -0
- package/src/agents/spatial-comms/__tests__/performance-benchmark.test.ts +465 -0
- package/src/agents/spatial-comms/examples/multi-agent-world-creation.ts +409 -0
- package/src/agents/spatial-comms/index.ts +66 -0
- package/src/ai/AIAdapter.ts +313 -0
- package/src/ai/AICopilot.ts +331 -0
- package/src/ai/AIOutputValidator.ts +203 -0
- package/src/ai/BTNodes.ts +239 -0
- package/src/ai/BehaviorSelector.ts +135 -0
- package/src/ai/BehaviorTree.ts +153 -0
- package/src/ai/Blackboard.ts +165 -0
- package/src/ai/GenerationAnalytics.ts +461 -0
- package/src/ai/GenerationCache.ts +265 -0
- package/src/ai/GoalPlanner.ts +165 -0
- package/src/ai/HoloScriptGenerator.ts +580 -0
- package/src/ai/InfluenceMap.ts +180 -0
- package/src/ai/NavMesh.ts +168 -0
- package/src/ai/PerceptionSystem.ts +178 -0
- package/src/ai/PromptTemplates.ts +453 -0
- package/src/ai/SemanticSearchService.ts +80 -0
- package/src/ai/StateMachine.ts +196 -0
- package/src/ai/SteeringBehavior.ts +150 -0
- package/src/ai/SteeringBehaviors.ts +244 -0
- package/src/ai/TrainingDataGenerator.ts +1082 -0
- package/src/ai/UtilityAI.ts +145 -0
- package/src/ai/__tests__/AIAdapter.prod.test.ts +259 -0
- package/src/ai/__tests__/AIAdapter.test.ts +109 -0
- package/src/ai/__tests__/AICopilot.prod.test.ts +341 -0
- package/src/ai/__tests__/AICopilot.test.ts +178 -0
- package/src/ai/__tests__/AIOutputValidator.prod.test.ts +226 -0
- package/src/ai/__tests__/AIOutputValidator.test.ts +138 -0
- package/src/ai/__tests__/BTNodes.prod.test.ts +391 -0
- package/src/ai/__tests__/BTNodes.test.ts +263 -0
- package/src/ai/__tests__/BehaviorSelector.prod.test.ts +129 -0
- package/src/ai/__tests__/BehaviorSelector.test.ts +132 -0
- package/src/ai/__tests__/BehaviorTree.prod.test.ts +266 -0
- package/src/ai/__tests__/BehaviorTree.test.ts +216 -0
- package/src/ai/__tests__/Blackboard.prod.test.ts +339 -0
- package/src/ai/__tests__/Blackboard.test.ts +183 -0
- package/src/ai/__tests__/GenerationAnalytics.prod.test.ts +141 -0
- package/src/ai/__tests__/GenerationAnalytics.test.ts +165 -0
- package/src/ai/__tests__/GenerationCache.prod.test.ts +144 -0
- package/src/ai/__tests__/GenerationCache.test.ts +171 -0
- package/src/ai/__tests__/GoalPlanner.prod.test.ts +189 -0
- package/src/ai/__tests__/GoalPlanner.test.ts +137 -0
- package/src/ai/__tests__/GoalPlannerDepth.prod.test.ts +217 -0
- package/src/ai/__tests__/HoloScriptGenerator.test.ts +125 -0
- package/src/ai/__tests__/InfluenceMap.prod.test.ts +146 -0
- package/src/ai/__tests__/InfluenceMap.test.ts +149 -0
- package/src/ai/__tests__/NavMesh.prod.test.ts +141 -0
- package/src/ai/__tests__/NavMesh.test.ts +159 -0
- package/src/ai/__tests__/PerceptionSystem.prod.test.ts +135 -0
- package/src/ai/__tests__/PerceptionSystem.test.ts +250 -0
- package/src/ai/__tests__/PromptTemplates.prod.test.ts +313 -0
- package/src/ai/__tests__/PromptTemplates.test.ts +146 -0
- package/src/ai/__tests__/SemanticSearch.test.ts +37 -0
- package/src/ai/__tests__/StateMachine.prod.test.ts +162 -0
- package/src/ai/__tests__/StateMachine.test.ts +163 -0
- package/src/ai/__tests__/SteeringBehavior.prod.test.ts +251 -0
- package/src/ai/__tests__/SteeringBehavior.test.ts +135 -0
- package/src/ai/__tests__/SteeringBehaviors.prod.test.ts +133 -0
- package/src/ai/__tests__/SteeringBehaviors.test.ts +151 -0
- package/src/ai/__tests__/TrainingDataGenerator.prod.test.ts +286 -0
- package/src/ai/__tests__/TrainingDataGenerator.test.ts +286 -0
- package/src/ai/__tests__/UtilityAI.prod.test.ts +207 -0
- package/src/ai/__tests__/UtilityAI.test.ts +155 -0
- package/src/ai/__tests__/adapters.prod.test.ts +263 -0
- package/src/ai/__tests__/adapters.test.ts +320 -0
- package/src/ai/adapters.ts +1585 -0
- package/src/ai/index.ts +130 -0
- package/src/behavior/BehaviorPresets.ts +140 -0
- package/src/behavior/BehaviorTree.ts +236 -0
- package/src/behavior/StateMachine.ts +176 -0
- package/src/behavior/StateTrait.ts +67 -0
- package/src/behavior/index.ts +8 -0
- package/src/behavior.ts +8 -0
- package/src/board/audit.ts +284 -0
- package/src/board/board-ops.ts +336 -0
- package/src/board/board-types.ts +302 -0
- package/src/board/index.ts +69 -0
- package/src/define-agent.ts +46 -0
- package/src/define-team.ts +33 -0
- package/src/delegation.ts +265 -0
- package/src/distributed-claimer.ts +228 -0
- package/src/economy/AgentBudgetEnforcer.ts +464 -0
- package/src/economy/BountyManager.ts +185 -0
- package/src/economy/CreatorRevenueAggregator.ts +460 -0
- package/src/economy/InvisibleWallet.ts +82 -0
- package/src/economy/KnowledgeMarketplace.ts +193 -0
- package/src/economy/PaymentWebhookService.ts +512 -0
- package/src/economy/RevenueSplitter.ts +156 -0
- package/src/economy/SubscriptionManager.ts +546 -0
- package/src/economy/UnifiedBudgetOptimizer.ts +635 -0
- package/src/economy/UsageMeter.ts +440 -0
- package/src/economy/_core-stubs.ts +219 -0
- package/src/economy/index.ts +100 -0
- package/src/economy/x402-facilitator.ts +1978 -0
- package/src/index.ts +348 -0
- package/src/knowledge/__tests__/knowledge-consolidator.test.ts +444 -0
- package/src/knowledge/__tests__/knowledge-store-vector.test.ts +291 -0
- package/src/knowledge/brain.ts +167 -0
- package/src/knowledge/consolidation.ts +581 -0
- package/src/knowledge/knowledge-consolidator.ts +510 -0
- package/src/knowledge/knowledge-store.ts +616 -0
- package/src/learning/MemoryConsolidator.ts +102 -0
- package/src/learning/MemoryScorer.ts +69 -0
- package/src/learning/ProceduralCompiler.ts +45 -0
- package/src/learning/SemanticClusterer.ts +66 -0
- package/src/learning/index.ts +8 -0
- package/src/llm/llm-adapter.ts +159 -0
- package/src/mesh/index.ts +309 -0
- package/src/negotiation/NegotiationProtocol.ts +694 -0
- package/src/negotiation/NegotiationTypes.ts +473 -0
- package/src/negotiation/VotingMechanisms.ts +691 -0
- package/src/negotiation/index.ts +49 -0
- package/src/protocol/goal-synthesizer.ts +317 -0
- package/src/protocol/implementations.ts +474 -0
- package/src/protocol/micro-phase-decomposer.ts +299 -0
- package/src/protocol/micro-step-decomposer.test.ts +306 -0
- package/src/protocol-agent.test.ts +353 -0
- package/src/protocol-agent.ts +670 -0
- package/src/self-improve/absorb-scanner.ts +252 -0
- package/src/self-improve/evolution-engine.ts +149 -0
- package/src/self-improve/framework-absorber.ts +214 -0
- package/src/self-improve/index.ts +50 -0
- package/src/self-improve/prompt-optimizer.ts +212 -0
- package/src/self-improve/test-generator.ts +175 -0
- package/src/skill-router.ts +186 -0
- package/src/skills/index.ts +5 -0
- package/src/skills/skill-md-bridge.ts +1699 -0
- package/src/swarm/ACOEngine.ts +261 -0
- package/src/swarm/CollectiveIntelligence.ts +383 -0
- package/src/swarm/ContributionSynthesizer.ts +481 -0
- package/src/swarm/LeaderElection.ts +393 -0
- package/src/swarm/PSOEngine.ts +206 -0
- package/src/swarm/QuorumPolicy.ts +173 -0
- package/src/swarm/SwarmCoordinator.ts +335 -0
- package/src/swarm/SwarmManager.ts +442 -0
- package/src/swarm/SwarmMembership.ts +456 -0
- package/src/swarm/VotingRound.ts +255 -0
- package/src/swarm/__tests__/ACOEngine.prod.test.ts +164 -0
- package/src/swarm/__tests__/ACOEngine.test.ts +117 -0
- package/src/swarm/__tests__/CollectiveIntelligence.prod.test.ts +296 -0
- package/src/swarm/__tests__/CollectiveIntelligence.test.ts +457 -0
- package/src/swarm/__tests__/ContributionSynthesizer.prod.test.ts +269 -0
- package/src/swarm/__tests__/ContributionSynthesizer.test.ts +254 -0
- package/src/swarm/__tests__/LeaderElection.prod.test.ts +196 -0
- package/src/swarm/__tests__/LeaderElection.test.ts +151 -0
- package/src/swarm/__tests__/PSOEngine.prod.test.ts +162 -0
- package/src/swarm/__tests__/PSOEngine.test.ts +106 -0
- package/src/swarm/__tests__/QuorumPolicy.prod.test.ts +216 -0
- package/src/swarm/__tests__/QuorumPolicy.test.ts +177 -0
- package/src/swarm/__tests__/SwarmCoordinator.prod.test.ts +186 -0
- package/src/swarm/__tests__/SwarmCoordinator.test.ts +167 -0
- package/src/swarm/__tests__/SwarmManager.prod.test.ts +308 -0
- package/src/swarm/__tests__/SwarmManager.test.ts +373 -0
- package/src/swarm/__tests__/SwarmMembership.prod.test.ts +273 -0
- package/src/swarm/__tests__/SwarmMembership.test.ts +264 -0
- package/src/swarm/__tests__/VotingRound.prod.test.ts +233 -0
- package/src/swarm/__tests__/VotingRound.test.ts +174 -0
- package/src/swarm/analytics/SwarmInspector.ts +476 -0
- package/src/swarm/analytics/SwarmMetrics.ts +449 -0
- package/src/swarm/analytics/__tests__/SwarmInspector.prod.test.ts +366 -0
- package/src/swarm/analytics/__tests__/SwarmInspector.test.ts +454 -0
- package/src/swarm/analytics/__tests__/SwarmMetrics.prod.test.ts +254 -0
- package/src/swarm/analytics/__tests__/SwarmMetrics.test.ts +370 -0
- package/src/swarm/analytics/index.ts +7 -0
- package/src/swarm/index.ts +69 -0
- package/src/swarm/messaging/BroadcastChannel.ts +509 -0
- package/src/swarm/messaging/GossipProtocol.ts +565 -0
- package/src/swarm/messaging/SwarmEventBus.ts +443 -0
- package/src/swarm/messaging/__tests__/BroadcastChannel.prod.test.ts +331 -0
- package/src/swarm/messaging/__tests__/BroadcastChannel.test.ts +333 -0
- package/src/swarm/messaging/__tests__/GossipProtocol.prod.test.ts +356 -0
- package/src/swarm/messaging/__tests__/GossipProtocol.test.ts +437 -0
- package/src/swarm/messaging/__tests__/SwarmEventBus.prod.test.ts +191 -0
- package/src/swarm/messaging/__tests__/SwarmEventBus.test.ts +247 -0
- package/src/swarm/messaging/index.ts +8 -0
- package/src/swarm/spatial/FlockingBehavior.ts +462 -0
- package/src/swarm/spatial/FormationController.ts +500 -0
- package/src/swarm/spatial/Vector3.ts +170 -0
- package/src/swarm/spatial/ZoneClaiming.ts +509 -0
- package/src/swarm/spatial/__tests__/FlockingBehavior.prod.test.ts +239 -0
- package/src/swarm/spatial/__tests__/FlockingBehavior.test.ts +298 -0
- package/src/swarm/spatial/__tests__/FormationController.prod.test.ts +240 -0
- package/src/swarm/spatial/__tests__/FormationController.test.ts +297 -0
- package/src/swarm/spatial/__tests__/Vector3.prod.test.ts +283 -0
- package/src/swarm/spatial/__tests__/Vector3.test.ts +224 -0
- package/src/swarm/spatial/__tests__/ZoneClaiming.prod.test.ts +246 -0
- package/src/swarm/spatial/__tests__/ZoneClaiming.test.ts +374 -0
- package/src/swarm/spatial/index.ts +28 -0
- package/src/team.ts +1245 -0
- package/src/training/LRScheduler.ts +377 -0
- package/src/training/QualityScoringPipeline.ts +139 -0
- package/src/training/SoftDedup.ts +461 -0
- package/src/training/SparsityMonitor.ts +685 -0
- package/src/training/SparsityMonitorTypes.ts +209 -0
- package/src/training/SpatialTrainingDataGenerator.ts +1526 -0
- package/src/training/SpatialTrainingDataTypes.ts +216 -0
- package/src/training/TrainingPipelineConfig.ts +215 -0
- package/src/training/constants.ts +94 -0
- package/src/training/index.ts +138 -0
- package/src/training/schema.ts +147 -0
- package/src/training/scripts/generate-novel-use-cases-dataset.ts +272 -0
- package/src/training/scripts/generate-spatial-dataset.ts +521 -0
- package/src/training/training/data/novel-use-cases.jsonl +153 -0
- package/src/training/training/data/spatial-reasoning-10k.jsonl +9354 -0
- package/src/training/trainingmonkey/TrainingMonkeyIntegration.ts +477 -0
- package/src/training/trainingmonkey/TrainingMonkeyTypes.ts +230 -0
- package/src/training/trainingmonkey/index.ts +26 -0
- package/src/training/trait-mappings.ts +157 -0
- package/src/types/core-stubs.d.ts +113 -0
- package/src/types.ts +304 -0
- package/test-output.txt +0 -0
- package/test-result.json +1 -0
- package/tsc-errors.txt +4 -0
- package/tsc_output.txt +0 -0
- package/tsconfig.json +14 -0
- package/tsup-learning-esm.config.ts +12 -0
- package/tsup.config.ts +21 -0
- package/typescript-errors-2.txt +0 -0
- package/typescript-errors.txt +22 -0
- package/vitest-log-utf8.txt +268 -0
- package/vitest-log.txt +0 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Authenticated CRDTs — DID-Signed Conflict-Free State Sync
|
|
3
|
+
* @module @holoscript/core/agents
|
|
4
|
+
*
|
|
5
|
+
* CRDTs (Conflict-free Replicated Data Types) for cross-device agent state.
|
|
6
|
+
* Every operation is DID-signed, enabling trustworthy decentralized sync.
|
|
7
|
+
*
|
|
8
|
+
* Merge functions reject untrusted, revoked, or out-of-scope operations.
|
|
9
|
+
* Overhead: ~0.1ms per merge operation.
|
|
10
|
+
*
|
|
11
|
+
* Implements:
|
|
12
|
+
* - LWW-Register: Last-Writer-Wins for atomic values
|
|
13
|
+
* - G-Counter: Grow-only counter for monotonic metrics
|
|
14
|
+
* - OR-Set: Observed-Remove set for collections
|
|
15
|
+
*
|
|
16
|
+
* @version 1.0.0
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// DID SIGNATURES
|
|
21
|
+
// =============================================================================
|
|
22
|
+
|
|
23
|
+
/** A DID (Decentralized Identifier) for agent identity */
|
|
24
|
+
export interface DID {
|
|
25
|
+
/** The DID string (e.g., "did:key:z6Mk...") */
|
|
26
|
+
id: string;
|
|
27
|
+
/** Device ID that generated this signature */
|
|
28
|
+
deviceId: string;
|
|
29
|
+
/** Capability scope (what this DID is allowed to modify) */
|
|
30
|
+
scope: string[];
|
|
31
|
+
/** Whether this DID has been revoked */
|
|
32
|
+
revoked: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** A signed operation */
|
|
36
|
+
export interface SignedOperation<T> {
|
|
37
|
+
/** The operation payload */
|
|
38
|
+
payload: T;
|
|
39
|
+
/** Signer DID */
|
|
40
|
+
signer: DID;
|
|
41
|
+
/** Timestamp (Lamport logical clock) */
|
|
42
|
+
timestamp: number;
|
|
43
|
+
/** Signature hash (hex string) */
|
|
44
|
+
signature: string;
|
|
45
|
+
/** Scope tag for capability checking */
|
|
46
|
+
scopeTag: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Simple hash function for signatures (non-cryptographic, for demo).
|
|
51
|
+
* In production, use Ed25519 or similar.
|
|
52
|
+
*/
|
|
53
|
+
function computeSignature(payload: unknown, signer: DID, timestamp: number): string {
|
|
54
|
+
const data = JSON.stringify({ payload, signer: signer.id, timestamp });
|
|
55
|
+
let hash = 0;
|
|
56
|
+
for (let i = 0; i < data.length; i++) {
|
|
57
|
+
hash = ((hash << 5) - hash + data.charCodeAt(i)) | 0;
|
|
58
|
+
}
|
|
59
|
+
return Math.abs(hash).toString(16).padStart(8, '0');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Sign an operation with a DID.
|
|
64
|
+
*/
|
|
65
|
+
export function signOperation<T>(
|
|
66
|
+
payload: T,
|
|
67
|
+
signer: DID,
|
|
68
|
+
scopeTag: string,
|
|
69
|
+
timestamp: number
|
|
70
|
+
): SignedOperation<T> {
|
|
71
|
+
return {
|
|
72
|
+
payload,
|
|
73
|
+
signer,
|
|
74
|
+
timestamp,
|
|
75
|
+
signature: computeSignature(payload, signer, timestamp),
|
|
76
|
+
scopeTag,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Verify a signed operation: check non-revoked and scope.
|
|
82
|
+
*/
|
|
83
|
+
export function verifyOperation<T>(op: SignedOperation<T>): { valid: boolean; reason?: string } {
|
|
84
|
+
if (op.signer.revoked) return { valid: false, reason: 'Signer DID revoked' };
|
|
85
|
+
if (!op.signer.scope.includes(op.scopeTag) && !op.signer.scope.includes('*')) {
|
|
86
|
+
return { valid: false, reason: `Signer lacks scope '${op.scopeTag}'` };
|
|
87
|
+
}
|
|
88
|
+
const expected = computeSignature(op.payload, op.signer, op.timestamp);
|
|
89
|
+
if (op.signature !== expected) return { valid: false, reason: 'Signature mismatch' };
|
|
90
|
+
return { valid: true };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// =============================================================================
|
|
94
|
+
// LWW-REGISTER — Last-Writer-Wins Register
|
|
95
|
+
// =============================================================================
|
|
96
|
+
|
|
97
|
+
/** A last-writer-wins register for a single value */
|
|
98
|
+
export class LWWRegister<T> {
|
|
99
|
+
private value: T;
|
|
100
|
+
private timestamp: number;
|
|
101
|
+
private lastSigner: DID | null;
|
|
102
|
+
private history: SignedOperation<T>[] = [];
|
|
103
|
+
|
|
104
|
+
constructor(initialValue: T) {
|
|
105
|
+
this.value = initialValue;
|
|
106
|
+
this.timestamp = 0;
|
|
107
|
+
this.lastSigner = null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Get current value */
|
|
111
|
+
get(): T {
|
|
112
|
+
return this.value;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Get last write timestamp */
|
|
116
|
+
getTimestamp(): number {
|
|
117
|
+
return this.timestamp;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Set value with a signed operation */
|
|
121
|
+
set(op: SignedOperation<T>): { accepted: boolean; reason?: string } {
|
|
122
|
+
const verification = verifyOperation(op);
|
|
123
|
+
if (!verification.valid) return { accepted: false, reason: verification.reason };
|
|
124
|
+
if (op.timestamp <= this.timestamp) return { accepted: false, reason: 'Stale timestamp' };
|
|
125
|
+
|
|
126
|
+
this.value = op.payload;
|
|
127
|
+
this.timestamp = op.timestamp;
|
|
128
|
+
this.lastSigner = op.signer;
|
|
129
|
+
this.history.push(op);
|
|
130
|
+
return { accepted: true };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Merge with another register (LWW semantics) */
|
|
134
|
+
merge(other: LWWRegister<T>): void {
|
|
135
|
+
if (other.timestamp > this.timestamp) {
|
|
136
|
+
this.value = other.value;
|
|
137
|
+
this.timestamp = other.timestamp;
|
|
138
|
+
this.lastSigner = other.lastSigner;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Get operation history */
|
|
143
|
+
getHistory(): SignedOperation<T>[] {
|
|
144
|
+
return [...this.history];
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// =============================================================================
|
|
149
|
+
// G-COUNTER — Grow-Only Counter
|
|
150
|
+
// =============================================================================
|
|
151
|
+
|
|
152
|
+
/** A grow-only counter (each node can only increment) */
|
|
153
|
+
export class GCounter {
|
|
154
|
+
private counts: Map<string, number> = new Map(); // nodeId → count
|
|
155
|
+
|
|
156
|
+
/** Increment for a specific node */
|
|
157
|
+
increment(nodeId: string, amount: number = 1): void {
|
|
158
|
+
this.counts.set(nodeId, (this.counts.get(nodeId) || 0) + amount);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Get the total value */
|
|
162
|
+
value(): number {
|
|
163
|
+
let total = 0;
|
|
164
|
+
for (const v of this.counts.values()) total += v;
|
|
165
|
+
return total;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Get the count for a specific node */
|
|
169
|
+
nodeValue(nodeId: string): number {
|
|
170
|
+
return this.counts.get(nodeId) || 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** Merge with another counter (take max per node) */
|
|
174
|
+
merge(other: GCounter): void {
|
|
175
|
+
for (const [nodeId, count] of other.counts) {
|
|
176
|
+
this.counts.set(nodeId, Math.max(this.counts.get(nodeId) || 0, count));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** Export state */
|
|
181
|
+
toJSON(): Record<string, number> {
|
|
182
|
+
const obj: Record<string, number> = {};
|
|
183
|
+
for (const [k, v] of this.counts) obj[k] = v;
|
|
184
|
+
return obj;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Import state */
|
|
188
|
+
static fromJSON(data: Record<string, number>): GCounter {
|
|
189
|
+
const counter = new GCounter();
|
|
190
|
+
for (const [k, v] of Object.entries(data)) counter.counts.set(k, v);
|
|
191
|
+
return counter;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// =============================================================================
|
|
196
|
+
// OR-SET — Observed-Remove Set
|
|
197
|
+
// =============================================================================
|
|
198
|
+
|
|
199
|
+
/** An element in an OR-Set, tagged with a unique ID */
|
|
200
|
+
interface ORSetElement<T> {
|
|
201
|
+
value: T;
|
|
202
|
+
tag: string; // Unique tag for this add operation
|
|
203
|
+
signer: DID;
|
|
204
|
+
timestamp: number;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** An observed-remove set: concurrent adds always win over removes */
|
|
208
|
+
export class ORSet<T> {
|
|
209
|
+
private elements: Map<string, ORSetElement<T>> = new Map(); // tag → element
|
|
210
|
+
private tombstones: Set<string> = new Set(); // removed tags
|
|
211
|
+
private tagCounter: number = 0;
|
|
212
|
+
|
|
213
|
+
/** Add an element with a signed operation */
|
|
214
|
+
add(value: T, signer: DID, timestamp: number): string {
|
|
215
|
+
if (signer.revoked) return '';
|
|
216
|
+
const tag = `${signer.id}_${timestamp}_${this.tagCounter++}`;
|
|
217
|
+
this.elements.set(tag, { value, tag, signer, timestamp });
|
|
218
|
+
return tag;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Remove an element by value (removes all copies) */
|
|
222
|
+
remove(value: T, _signer: DID): number {
|
|
223
|
+
let removed = 0;
|
|
224
|
+
for (const [tag, elem] of this.elements) {
|
|
225
|
+
if (this.valueEquals(elem.value, value)) {
|
|
226
|
+
this.tombstones.add(tag);
|
|
227
|
+
this.elements.delete(tag);
|
|
228
|
+
removed++;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return removed;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Check if the set contains a value */
|
|
235
|
+
has(value: T): boolean {
|
|
236
|
+
for (const elem of this.elements.values()) {
|
|
237
|
+
if (this.valueEquals(elem.value, value)) return true;
|
|
238
|
+
}
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** Get all current values (deduplicated) */
|
|
243
|
+
values(): T[] {
|
|
244
|
+
const seen = new Set<string>();
|
|
245
|
+
const result: T[] = [];
|
|
246
|
+
for (const elem of this.elements.values()) {
|
|
247
|
+
const key = JSON.stringify(elem.value);
|
|
248
|
+
if (!seen.has(key)) {
|
|
249
|
+
seen.add(key);
|
|
250
|
+
result.push(elem.value);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** Size of the set (unique values) */
|
|
257
|
+
get size(): number {
|
|
258
|
+
return this.values().length;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** Merge with another OR-Set (adds win over concurrent removes) */
|
|
262
|
+
merge(other: ORSet<T>): void {
|
|
263
|
+
// Add all elements from other that we haven't tombstoned
|
|
264
|
+
for (const [tag, elem] of other.elements) {
|
|
265
|
+
if (!this.tombstones.has(tag) && !this.elements.has(tag)) {
|
|
266
|
+
// Verify signer is not revoked
|
|
267
|
+
if (!elem.signer.revoked) {
|
|
268
|
+
this.elements.set(tag, elem);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// Apply other's tombstones
|
|
273
|
+
for (const tag of other.tombstones) {
|
|
274
|
+
this.tombstones.add(tag);
|
|
275
|
+
this.elements.delete(tag);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
private valueEquals(a: T, b: T): boolean {
|
|
280
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// =============================================================================
|
|
285
|
+
// AUTHENTICATED STATE — Combines CRDTs with DID auth
|
|
286
|
+
// =============================================================================
|
|
287
|
+
|
|
288
|
+
/** A complete authenticated agent state document */
|
|
289
|
+
export interface AuthenticatedAgentState {
|
|
290
|
+
/** Agent DID */
|
|
291
|
+
agentDID: string;
|
|
292
|
+
/** State registers (key-value pairs) */
|
|
293
|
+
registers: Map<string, LWWRegister<unknown>>;
|
|
294
|
+
/** Counters */
|
|
295
|
+
counters: Map<string, GCounter>;
|
|
296
|
+
/** Sets */
|
|
297
|
+
sets: Map<string, ORSet<unknown>>;
|
|
298
|
+
/** Last sync timestamp */
|
|
299
|
+
lastSync: number;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Create a new authenticated agent state.
|
|
304
|
+
*/
|
|
305
|
+
export function createAgentState(agentDID: string): AuthenticatedAgentState {
|
|
306
|
+
return {
|
|
307
|
+
agentDID,
|
|
308
|
+
registers: new Map(),
|
|
309
|
+
counters: new Map(),
|
|
310
|
+
sets: new Map(),
|
|
311
|
+
lastSync: 0,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Set a register value with authentication.
|
|
317
|
+
*/
|
|
318
|
+
export function setRegister(
|
|
319
|
+
state: AuthenticatedAgentState,
|
|
320
|
+
key: string,
|
|
321
|
+
value: unknown,
|
|
322
|
+
signer: DID,
|
|
323
|
+
timestamp: number
|
|
324
|
+
): { accepted: boolean; reason?: string } {
|
|
325
|
+
if (!state.registers.has(key)) {
|
|
326
|
+
state.registers.set(key, new LWWRegister(undefined));
|
|
327
|
+
}
|
|
328
|
+
const op = signOperation(value, signer, `state:${key}`, timestamp);
|
|
329
|
+
return state.registers.get(key)!.set(op as SignedOperation<unknown>);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Get a register value.
|
|
334
|
+
*/
|
|
335
|
+
export function getRegister<T>(state: AuthenticatedAgentState, key: string): T | undefined {
|
|
336
|
+
return state.registers.get(key)?.get() as T | undefined;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Increment a counter.
|
|
341
|
+
*/
|
|
342
|
+
export function incrementCounter(
|
|
343
|
+
state: AuthenticatedAgentState,
|
|
344
|
+
key: string,
|
|
345
|
+
nodeId: string,
|
|
346
|
+
amount: number = 1
|
|
347
|
+
): void {
|
|
348
|
+
if (!state.counters.has(key)) state.counters.set(key, new GCounter());
|
|
349
|
+
state.counters.get(key)!.increment(nodeId, amount);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Get a counter value.
|
|
354
|
+
*/
|
|
355
|
+
export function getCounter(state: AuthenticatedAgentState, key: string): number {
|
|
356
|
+
return state.counters.get(key)?.value() ?? 0;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Merge two agent states (CRDT merge — always converges).
|
|
361
|
+
*/
|
|
362
|
+
export function mergeStates(local: AuthenticatedAgentState, remote: AuthenticatedAgentState): void {
|
|
363
|
+
// Merge registers
|
|
364
|
+
for (const [key, reg] of remote.registers) {
|
|
365
|
+
if (local.registers.has(key)) {
|
|
366
|
+
local.registers.get(key)!.merge(reg);
|
|
367
|
+
} else {
|
|
368
|
+
local.registers.set(key, reg);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
// Merge counters
|
|
372
|
+
for (const [key, counter] of remote.counters) {
|
|
373
|
+
if (local.counters.has(key)) {
|
|
374
|
+
local.counters.get(key)!.merge(counter);
|
|
375
|
+
} else {
|
|
376
|
+
local.counters.set(key, counter);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
// Merge sets
|
|
380
|
+
for (const [key, set] of remote.sets) {
|
|
381
|
+
if (local.sets.has(key)) {
|
|
382
|
+
local.sets.get(key)!.merge(set);
|
|
383
|
+
} else {
|
|
384
|
+
local.sets.set(key, set);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
local.lastSync = Math.max(local.lastSync, remote.lastSync);
|
|
388
|
+
}
|