@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,670 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProtocolAgent — Concrete BaseAgent backed by LLM calls.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the 7-phase uAA2++ lifecycle around a team agent's task execution.
|
|
5
|
+
* Uses haiku-tier models for lightweight phases (reflect, compress, grow, evolve)
|
|
6
|
+
* and the agent's configured model for the execute phase.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { BaseAgent, ProtocolPhase } from './protocol/implementations';
|
|
10
|
+
import type { AgentIdentity, PhaseResult } from './protocol/implementations';
|
|
11
|
+
|
|
12
|
+
import { callLLM } from './llm/llm-adapter';
|
|
13
|
+
import type { LLMMessage } from './llm/llm-adapter';
|
|
14
|
+
import type {
|
|
15
|
+
AgentConfig,
|
|
16
|
+
ModelConfig,
|
|
17
|
+
KnowledgeInsight,
|
|
18
|
+
ProtocolAgentConfig,
|
|
19
|
+
ProtocolAgentHandle,
|
|
20
|
+
AgentStatus,
|
|
21
|
+
CycleResult as FrameworkCycleResult,
|
|
22
|
+
} from './types';
|
|
23
|
+
import type { ProtocolCycleResult } from './protocol/implementations';
|
|
24
|
+
|
|
25
|
+
// ── Phase-specific system prompts ──
|
|
26
|
+
|
|
27
|
+
const PHASE_PROMPTS: Record<number, string> = {
|
|
28
|
+
[ProtocolPhase.INTAKE]:
|
|
29
|
+
'You are gathering context for a task. Summarize the task, relevant knowledge, and constraints. Be concise.',
|
|
30
|
+
[ProtocolPhase.REFLECT]:
|
|
31
|
+
'You are analyzing an approach. Given the context, identify the best strategy, risks, and key considerations. Be brief.',
|
|
32
|
+
[ProtocolPhase.EXECUTE]:
|
|
33
|
+
'', // Uses the agent's own system prompt
|
|
34
|
+
[ProtocolPhase.COMPRESS]:
|
|
35
|
+
'You are extracting knowledge from completed work. Identify Wisdom (insights), Patterns (reusable solutions), and Gotchas (pitfalls). Format each as: [wisdom|pattern|gotcha] content',
|
|
36
|
+
[ProtocolPhase.REINTAKE]:
|
|
37
|
+
'You are validating extracted knowledge. Check for accuracy, remove duplicates, and rate confidence (0.0-1.0). Return only validated items.',
|
|
38
|
+
[ProtocolPhase.GROW]:
|
|
39
|
+
'You are identifying meta-patterns. Given validated knowledge, find cross-cutting themes and recurring patterns. Be concise.',
|
|
40
|
+
[ProtocolPhase.EVOLVE]:
|
|
41
|
+
'You are suggesting improvements. Based on patterns found, propose concrete optimizations for future work. Be brief and actionable.',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/** Model config for lightweight phases (haiku-tier). */
|
|
45
|
+
function lightModel(agentModel: ModelConfig): ModelConfig {
|
|
46
|
+
// Use same provider but prefer a cheaper model for non-execute phases.
|
|
47
|
+
// If the agent is already on a small model, just use it.
|
|
48
|
+
const cheapModels: Record<string, string> = {
|
|
49
|
+
anthropic: 'claude-haiku-4',
|
|
50
|
+
openai: 'gpt-4o-mini',
|
|
51
|
+
xai: 'grok-2',
|
|
52
|
+
openrouter: 'anthropic/claude-haiku-4',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
...agentModel,
|
|
57
|
+
model: cheapModels[agentModel.provider] ?? agentModel.model,
|
|
58
|
+
maxTokens: 512,
|
|
59
|
+
temperature: 0.3,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Result of executing a full protocol cycle on a task. */
|
|
64
|
+
export interface ProtocolTaskResult {
|
|
65
|
+
summary: string;
|
|
66
|
+
insights: KnowledgeInsight[];
|
|
67
|
+
phaseResults: PhaseResult[];
|
|
68
|
+
totalDurationMs: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export class ProtocolAgent extends BaseAgent {
|
|
72
|
+
readonly identity: AgentIdentity;
|
|
73
|
+
|
|
74
|
+
private agentConfig: AgentConfig;
|
|
75
|
+
private teamKnowledge: string;
|
|
76
|
+
private task: string;
|
|
77
|
+
|
|
78
|
+
constructor(agentConfig: AgentConfig, teamKnowledge: string = '') {
|
|
79
|
+
super();
|
|
80
|
+
this.agentConfig = agentConfig;
|
|
81
|
+
this.teamKnowledge = teamKnowledge;
|
|
82
|
+
this.task = '';
|
|
83
|
+
|
|
84
|
+
this.identity = {
|
|
85
|
+
id: `protocol_${agentConfig.name}`,
|
|
86
|
+
name: agentConfig.name,
|
|
87
|
+
domain: agentConfig.knowledgeDomains?.[0] ?? 'general',
|
|
88
|
+
version: '1.0.0',
|
|
89
|
+
capabilities: agentConfig.capabilities,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ── Phase implementations ──
|
|
94
|
+
|
|
95
|
+
async intake(input: unknown): Promise<PhaseResult> {
|
|
96
|
+
const { task } = input as { task: string };
|
|
97
|
+
this.task = task;
|
|
98
|
+
|
|
99
|
+
// INTAKE is local — no LLM call needed. Just structure the context.
|
|
100
|
+
const context = {
|
|
101
|
+
task,
|
|
102
|
+
agent: this.agentConfig.name,
|
|
103
|
+
role: this.agentConfig.role,
|
|
104
|
+
capabilities: this.agentConfig.capabilities,
|
|
105
|
+
knowledge: this.teamKnowledge,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
phase: ProtocolPhase.INTAKE,
|
|
110
|
+
status: 'success',
|
|
111
|
+
data: context,
|
|
112
|
+
durationMs: 0,
|
|
113
|
+
timestamp: Date.now(),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async reflect(data: unknown): Promise<PhaseResult> {
|
|
118
|
+
const context = data as Record<string, unknown>;
|
|
119
|
+
const messages: LLMMessage[] = [
|
|
120
|
+
{ role: 'system', content: PHASE_PROMPTS[ProtocolPhase.REFLECT] },
|
|
121
|
+
{
|
|
122
|
+
role: 'user',
|
|
123
|
+
content: `Task: ${context.task}\nRole: ${context.role}\nCapabilities: ${context.capabilities}\n${context.knowledge ? `Knowledge:\n${context.knowledge}` : ''}\n\nAnalyze the best approach.`,
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
const response = await callLLM(lightModel(this.agentConfig.model), messages);
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
phase: ProtocolPhase.REFLECT,
|
|
131
|
+
status: 'success',
|
|
132
|
+
data: { plan: response.content, context },
|
|
133
|
+
durationMs: 0,
|
|
134
|
+
timestamp: Date.now(),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async execute(plan: unknown): Promise<PhaseResult> {
|
|
139
|
+
const { context } = plan as { plan: string; context: Record<string, unknown> };
|
|
140
|
+
const agent = this.agentConfig;
|
|
141
|
+
|
|
142
|
+
const systemPrompt =
|
|
143
|
+
agent.systemPrompt ||
|
|
144
|
+
`You are ${agent.name}, a ${agent.role} agent. Your capabilities: ${agent.capabilities.join(', ')}.`;
|
|
145
|
+
|
|
146
|
+
const knowledgeContext = this.teamKnowledge
|
|
147
|
+
? `\n\nRelevant team knowledge:\n${this.teamKnowledge}`
|
|
148
|
+
: '';
|
|
149
|
+
|
|
150
|
+
const messages: LLMMessage[] = [
|
|
151
|
+
{ role: 'system', content: systemPrompt },
|
|
152
|
+
{
|
|
153
|
+
role: 'user',
|
|
154
|
+
content: `Task: ${context.task}\n${(context as Record<string, unknown>).description ?? ''}${knowledgeContext}\n\nComplete this task. Provide a clear summary of what you did.`,
|
|
155
|
+
},
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
// Execute phase uses the agent's full model (sonnet-tier).
|
|
159
|
+
const response = await callLLM(this.agentConfig.model, messages);
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
phase: ProtocolPhase.EXECUTE,
|
|
163
|
+
status: 'success',
|
|
164
|
+
data: { output: response.content, task: context.task },
|
|
165
|
+
durationMs: 0,
|
|
166
|
+
timestamp: Date.now(),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async compress(results: unknown): Promise<PhaseResult> {
|
|
171
|
+
const { output } = results as { output: string; task: string };
|
|
172
|
+
|
|
173
|
+
const messages: LLMMessage[] = [
|
|
174
|
+
{ role: 'system', content: PHASE_PROMPTS[ProtocolPhase.COMPRESS] },
|
|
175
|
+
{
|
|
176
|
+
role: 'user',
|
|
177
|
+
content: `Task: ${this.task}\nOutput:\n${output}\n\nExtract knowledge items. Format each on its own line as:\n[wisdom] insight here\n[pattern] reusable solution here\n[gotcha] pitfall here`,
|
|
178
|
+
},
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
const response = await callLLM(lightModel(this.agentConfig.model), messages);
|
|
182
|
+
const insights = parseKnowledgeItems(
|
|
183
|
+
response.content,
|
|
184
|
+
this.identity.domain,
|
|
185
|
+
this.agentConfig.name
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
phase: ProtocolPhase.COMPRESS,
|
|
190
|
+
status: 'success',
|
|
191
|
+
data: { insights, rawOutput: output },
|
|
192
|
+
durationMs: 0,
|
|
193
|
+
timestamp: Date.now(),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async reintake(compressed: unknown): Promise<PhaseResult> {
|
|
198
|
+
const { insights, rawOutput } = compressed as {
|
|
199
|
+
insights: KnowledgeInsight[];
|
|
200
|
+
rawOutput: string;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
if (insights.length === 0) {
|
|
204
|
+
return {
|
|
205
|
+
phase: ProtocolPhase.REINTAKE,
|
|
206
|
+
status: 'success',
|
|
207
|
+
data: { validated: [], rawOutput },
|
|
208
|
+
durationMs: 0,
|
|
209
|
+
timestamp: Date.now(),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const messages: LLMMessage[] = [
|
|
214
|
+
{ role: 'system', content: PHASE_PROMPTS[ProtocolPhase.REINTAKE] },
|
|
215
|
+
{
|
|
216
|
+
role: 'user',
|
|
217
|
+
content: `Validate these knowledge items:\n${insights.map((i) => `[${i.type}] ${i.content}`).join('\n')}\n\nReturn only the validated items, one per line as: [type] content`,
|
|
218
|
+
},
|
|
219
|
+
];
|
|
220
|
+
|
|
221
|
+
const response = await callLLM(lightModel(this.agentConfig.model), messages);
|
|
222
|
+
const validated = parseKnowledgeItems(
|
|
223
|
+
response.content,
|
|
224
|
+
this.identity.domain,
|
|
225
|
+
this.agentConfig.name
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
phase: ProtocolPhase.REINTAKE,
|
|
230
|
+
status: 'success',
|
|
231
|
+
data: { validated: validated.length > 0 ? validated : insights, rawOutput },
|
|
232
|
+
durationMs: 0,
|
|
233
|
+
timestamp: Date.now(),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async grow(learnings: unknown): Promise<PhaseResult> {
|
|
238
|
+
const { validated } = learnings as { validated: KnowledgeInsight[]; rawOutput: string };
|
|
239
|
+
|
|
240
|
+
if (validated.length === 0) {
|
|
241
|
+
return {
|
|
242
|
+
phase: ProtocolPhase.GROW,
|
|
243
|
+
status: 'success',
|
|
244
|
+
data: { patterns: [], validated },
|
|
245
|
+
durationMs: 0,
|
|
246
|
+
timestamp: Date.now(),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const messages: LLMMessage[] = [
|
|
251
|
+
{ role: 'system', content: PHASE_PROMPTS[ProtocolPhase.GROW] },
|
|
252
|
+
{
|
|
253
|
+
role: 'user',
|
|
254
|
+
content: `Knowledge items:\n${validated.map((i) => `[${i.type}] ${i.content}`).join('\n')}\n\nIdentify cross-cutting patterns or themes.`,
|
|
255
|
+
},
|
|
256
|
+
];
|
|
257
|
+
|
|
258
|
+
const response = await callLLM(lightModel(this.agentConfig.model), messages);
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
phase: ProtocolPhase.GROW,
|
|
262
|
+
status: 'success',
|
|
263
|
+
data: { patterns: response.content, validated },
|
|
264
|
+
durationMs: 0,
|
|
265
|
+
timestamp: Date.now(),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async evolve(adaptations: unknown): Promise<PhaseResult> {
|
|
270
|
+
const { validated } = adaptations as { patterns: string; validated: KnowledgeInsight[] };
|
|
271
|
+
|
|
272
|
+
if (validated.length === 0) {
|
|
273
|
+
return {
|
|
274
|
+
phase: ProtocolPhase.EVOLVE,
|
|
275
|
+
status: 'success',
|
|
276
|
+
data: { suggestions: 'No knowledge to evolve from.' },
|
|
277
|
+
durationMs: 0,
|
|
278
|
+
timestamp: Date.now(),
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const messages: LLMMessage[] = [
|
|
283
|
+
{ role: 'system', content: PHASE_PROMPTS[ProtocolPhase.EVOLVE] },
|
|
284
|
+
{
|
|
285
|
+
role: 'user',
|
|
286
|
+
content: `Based on patterns found, suggest improvements for future tasks in domain "${this.identity.domain}".`,
|
|
287
|
+
},
|
|
288
|
+
];
|
|
289
|
+
|
|
290
|
+
const response = await callLLM(lightModel(this.agentConfig.model), messages);
|
|
291
|
+
|
|
292
|
+
return {
|
|
293
|
+
phase: ProtocolPhase.EVOLVE,
|
|
294
|
+
status: 'success',
|
|
295
|
+
data: { suggestions: response.content },
|
|
296
|
+
durationMs: 0,
|
|
297
|
+
timestamp: Date.now(),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ── Helpers ──
|
|
303
|
+
|
|
304
|
+
/** Parse LLM output into KnowledgeInsight[]. */
|
|
305
|
+
function parseKnowledgeItems(
|
|
306
|
+
content: string,
|
|
307
|
+
domain: string,
|
|
308
|
+
source: string
|
|
309
|
+
): KnowledgeInsight[] {
|
|
310
|
+
const insights: KnowledgeInsight[] = [];
|
|
311
|
+
|
|
312
|
+
for (const line of content.split('\n')) {
|
|
313
|
+
const trimmed = line.trim();
|
|
314
|
+
// Match both "- [type] content" and "[type] content"
|
|
315
|
+
const match = trimmed.match(/^(?:-\s*)?\[(wisdom|pattern|gotcha)\]\s*(.+)$/i);
|
|
316
|
+
if (match) {
|
|
317
|
+
insights.push({
|
|
318
|
+
type: match[1].toLowerCase() as 'wisdom' | 'pattern' | 'gotcha',
|
|
319
|
+
content: match[2].trim(),
|
|
320
|
+
domain,
|
|
321
|
+
confidence: 0.7,
|
|
322
|
+
source,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return insights;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Execute a full protocol cycle for a task and extract the structured result.
|
|
332
|
+
* This is the main entry point used by Team.executeTask.
|
|
333
|
+
*/
|
|
334
|
+
export async function runProtocolCycle(
|
|
335
|
+
agentConfig: AgentConfig,
|
|
336
|
+
task: { title: string; description: string },
|
|
337
|
+
teamKnowledge: string
|
|
338
|
+
): Promise<ProtocolTaskResult> {
|
|
339
|
+
const agent = new ProtocolAgent(agentConfig, teamKnowledge);
|
|
340
|
+
const start = Date.now();
|
|
341
|
+
|
|
342
|
+
const cycleResult = await agent.runCycle(task.title, {
|
|
343
|
+
description: task.description,
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// Extract summary from EXECUTE phase
|
|
347
|
+
const executePhase = cycleResult.phases.find(
|
|
348
|
+
(p) => p.phase === ProtocolPhase.EXECUTE
|
|
349
|
+
);
|
|
350
|
+
const summary =
|
|
351
|
+
(executePhase?.data as { output?: string })?.output?.slice(0, 500) ??
|
|
352
|
+
'Task completed';
|
|
353
|
+
|
|
354
|
+
// Extract insights from REINTAKE phase (validated) or COMPRESS phase (raw)
|
|
355
|
+
const reintakePhase = cycleResult.phases.find(
|
|
356
|
+
(p) => p.phase === ProtocolPhase.REINTAKE
|
|
357
|
+
);
|
|
358
|
+
const compressPhase = cycleResult.phases.find(
|
|
359
|
+
(p) => p.phase === ProtocolPhase.COMPRESS
|
|
360
|
+
);
|
|
361
|
+
const insights: KnowledgeInsight[] =
|
|
362
|
+
(reintakePhase?.data as { validated?: KnowledgeInsight[] })?.validated ??
|
|
363
|
+
(compressPhase?.data as { insights?: KnowledgeInsight[] })?.insights ??
|
|
364
|
+
[];
|
|
365
|
+
|
|
366
|
+
return {
|
|
367
|
+
summary,
|
|
368
|
+
insights,
|
|
369
|
+
phaseResults: cycleResult.phases,
|
|
370
|
+
totalDurationMs: Date.now() - start,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// ── CycleResult Adapter ──
|
|
375
|
+
// Maps framework CycleResult (team-oriented) ↔ protocol ProtocolCycleResult (agent-oriented).
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Convert a protocol ProtocolCycleResult into the framework's team-oriented CycleResult.
|
|
379
|
+
*/
|
|
380
|
+
export function protocolToFrameworkCycleResult(
|
|
381
|
+
protocol: ProtocolCycleResult,
|
|
382
|
+
teamName: string,
|
|
383
|
+
cycle: number
|
|
384
|
+
): FrameworkCycleResult {
|
|
385
|
+
// Extract insights from compress/reintake phases
|
|
386
|
+
const reintake = protocol.phases.find(p => p.phase === ProtocolPhase.REINTAKE);
|
|
387
|
+
const compress = protocol.phases.find(p => p.phase === ProtocolPhase.COMPRESS);
|
|
388
|
+
const insights: KnowledgeInsight[] =
|
|
389
|
+
(reintake?.data as { validated?: KnowledgeInsight[] })?.validated ??
|
|
390
|
+
(compress?.data as { insights?: KnowledgeInsight[] })?.insights ??
|
|
391
|
+
[];
|
|
392
|
+
|
|
393
|
+
const executePhase = protocol.phases.find(p => p.phase === ProtocolPhase.EXECUTE);
|
|
394
|
+
const summary = (executePhase?.data as { output?: string })?.output?.slice(0, 500) ?? 'Task completed';
|
|
395
|
+
|
|
396
|
+
const hasFailed = protocol.status === 'failed';
|
|
397
|
+
|
|
398
|
+
return {
|
|
399
|
+
teamName,
|
|
400
|
+
cycle,
|
|
401
|
+
agentResults: [{
|
|
402
|
+
agentName: protocol.domain, // best available identifier
|
|
403
|
+
taskId: protocol.cycleId,
|
|
404
|
+
taskTitle: protocol.task,
|
|
405
|
+
action: hasFailed ? 'error' : 'completed',
|
|
406
|
+
summary,
|
|
407
|
+
knowledge: insights,
|
|
408
|
+
}],
|
|
409
|
+
knowledgeProduced: insights,
|
|
410
|
+
compoundedInsights: insights.length,
|
|
411
|
+
durationMs: protocol.totalDurationMs,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Convert a framework CycleResult into a protocol ProtocolCycleResult.
|
|
417
|
+
*/
|
|
418
|
+
export function frameworkToProtocolCycleResult(
|
|
419
|
+
fw: FrameworkCycleResult,
|
|
420
|
+
task: string,
|
|
421
|
+
domain: string
|
|
422
|
+
): ProtocolCycleResult {
|
|
423
|
+
const now = Date.now();
|
|
424
|
+
const hasError = fw.agentResults.some(r => r.action === 'error');
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
cycleId: `cycle_${fw.cycle}_${now.toString(36)}`,
|
|
428
|
+
task,
|
|
429
|
+
domain,
|
|
430
|
+
phases: [], // framework CycleResult doesn't carry per-phase data
|
|
431
|
+
status: hasError ? 'failed' : 'complete',
|
|
432
|
+
totalDurationMs: fw.durationMs,
|
|
433
|
+
startedAt: now - fw.durationMs,
|
|
434
|
+
completedAt: now,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// ── defineProtocolAgent() builder ──
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Creates a live protocol agent handle backed by LLM calls.
|
|
442
|
+
*
|
|
443
|
+
* The returned handle has execute(task), pause/resume/cancel controls,
|
|
444
|
+
* status tracking, and phase history.
|
|
445
|
+
*
|
|
446
|
+
* ```ts
|
|
447
|
+
* const agent = defineProtocolAgent({
|
|
448
|
+
* name: 'researcher',
|
|
449
|
+
* role: 'researcher',
|
|
450
|
+
* model: { provider: 'anthropic', model: 'claude-sonnet-4-20250514' },
|
|
451
|
+
* capabilities: ['search', 'summarize'],
|
|
452
|
+
* claimFilter: { roles: ['researcher'], maxPriority: 10 },
|
|
453
|
+
* });
|
|
454
|
+
* const result = await agent.execute({ title: 'Find X', description: 'Research X' });
|
|
455
|
+
* ```
|
|
456
|
+
*/
|
|
457
|
+
export function defineProtocolAgent(config: ProtocolAgentConfig): ProtocolAgentHandle {
|
|
458
|
+
// Validate config using same rules as defineAgent
|
|
459
|
+
if (!config.name || config.name.length < 1) {
|
|
460
|
+
throw new Error('Agent name is required');
|
|
461
|
+
}
|
|
462
|
+
const VALID_ROLES = ['architect', 'coder', 'researcher', 'reviewer'] as const;
|
|
463
|
+
if (!VALID_ROLES.includes(config.role as typeof VALID_ROLES[number])) {
|
|
464
|
+
throw new Error(`Invalid role "${config.role}". Valid: ${VALID_ROLES.join(', ')}`);
|
|
465
|
+
}
|
|
466
|
+
if (!config.model?.provider || !config.model?.model) {
|
|
467
|
+
throw new Error('Agent model must specify provider and model');
|
|
468
|
+
}
|
|
469
|
+
if (!config.capabilities || config.capabilities.length === 0) {
|
|
470
|
+
throw new Error('Agent must have at least one capability');
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
const protocolStyle = config.protocolStyle ?? 'uaa2';
|
|
474
|
+
if (protocolStyle !== 'uaa2') {
|
|
475
|
+
throw new Error(`Protocol style "${protocolStyle}" is not yet implemented. Only 'uaa2' is supported.`);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Internal mutable state
|
|
479
|
+
let status: AgentStatus = 'idle';
|
|
480
|
+
const phaseHistory: PhaseResult[] = [];
|
|
481
|
+
let pauseRequested = false;
|
|
482
|
+
let cancelRequested = false;
|
|
483
|
+
let pauseResolver: (() => void) | null = null;
|
|
484
|
+
|
|
485
|
+
const maxRetries = config.maxPhaseRetries ?? 1;
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Run a single phase with hooks, retries, and pause/cancel checks.
|
|
489
|
+
*/
|
|
490
|
+
async function runPhaseWithControls(
|
|
491
|
+
agent: ProtocolAgent,
|
|
492
|
+
phase: ProtocolPhase,
|
|
493
|
+
phaseFn: (input: unknown) => Promise<PhaseResult>,
|
|
494
|
+
input: unknown
|
|
495
|
+
): Promise<PhaseResult> {
|
|
496
|
+
// Check cancel
|
|
497
|
+
if (cancelRequested) {
|
|
498
|
+
const skipped: PhaseResult = {
|
|
499
|
+
phase,
|
|
500
|
+
status: 'skipped',
|
|
501
|
+
data: 'cancelled',
|
|
502
|
+
durationMs: 0,
|
|
503
|
+
timestamp: Date.now(),
|
|
504
|
+
};
|
|
505
|
+
phaseHistory.push(skipped);
|
|
506
|
+
return skipped;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Check pause — wait until resumed
|
|
510
|
+
if (pauseRequested) {
|
|
511
|
+
status = 'paused';
|
|
512
|
+
await new Promise<void>(resolve => {
|
|
513
|
+
pauseResolver = resolve;
|
|
514
|
+
});
|
|
515
|
+
status = 'running';
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Before hook
|
|
519
|
+
let phaseInput = input;
|
|
520
|
+
if (config.phaseHooks?.before) {
|
|
521
|
+
phaseInput = (await config.phaseHooks.before(phase, input)) ?? input;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Execute with retries
|
|
525
|
+
let lastError: unknown;
|
|
526
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
527
|
+
try {
|
|
528
|
+
const start = Date.now();
|
|
529
|
+
let result = await phaseFn.call(agent, phaseInput);
|
|
530
|
+
result.durationMs = Date.now() - start;
|
|
531
|
+
|
|
532
|
+
// After hook
|
|
533
|
+
if (config.phaseHooks?.after) {
|
|
534
|
+
result = (await config.phaseHooks.after(phase, result)) ?? result;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
phaseHistory.push(result);
|
|
538
|
+
return result;
|
|
539
|
+
} catch (err) {
|
|
540
|
+
lastError = err;
|
|
541
|
+
if (attempt === maxRetries - 1) break;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// All retries exhausted
|
|
546
|
+
const failResult: PhaseResult = {
|
|
547
|
+
phase,
|
|
548
|
+
status: 'failure',
|
|
549
|
+
data: lastError instanceof Error ? lastError.message : String(lastError),
|
|
550
|
+
durationMs: 0,
|
|
551
|
+
timestamp: Date.now(),
|
|
552
|
+
};
|
|
553
|
+
phaseHistory.push(failResult);
|
|
554
|
+
return failResult;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const handle: ProtocolAgentHandle = {
|
|
558
|
+
get name() { return config.name; },
|
|
559
|
+
get role() { return config.role; },
|
|
560
|
+
get status() { return status; },
|
|
561
|
+
get history() { return [...phaseHistory]; },
|
|
562
|
+
|
|
563
|
+
async execute(task: { title: string; description: string }): Promise<ProtocolCycleResult> {
|
|
564
|
+
if (status === 'running') {
|
|
565
|
+
throw new Error('Agent is already executing. Await the current execution or cancel() first.');
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
status = 'running';
|
|
569
|
+
pauseRequested = false;
|
|
570
|
+
cancelRequested = false;
|
|
571
|
+
|
|
572
|
+
const agent = new ProtocolAgent(config, config.teamKnowledge ?? '');
|
|
573
|
+
if (config.lightModel) {
|
|
574
|
+
// Apply light model overrides — handled inside ProtocolAgent via lightModel()
|
|
575
|
+
// The lightModel function in ProtocolAgent already handles this
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
const startedAt = Date.now();
|
|
579
|
+
const cycleId = `cycle_${startedAt}_${Math.random().toString(36).slice(2, 8)}`;
|
|
580
|
+
|
|
581
|
+
try {
|
|
582
|
+
// Run 7 phases sequentially with controls
|
|
583
|
+
const phases: Array<[ProtocolPhase, (input: unknown) => Promise<PhaseResult>]> = [
|
|
584
|
+
[ProtocolPhase.INTAKE, agent.intake],
|
|
585
|
+
[ProtocolPhase.REFLECT, agent.reflect],
|
|
586
|
+
[ProtocolPhase.EXECUTE, agent.execute],
|
|
587
|
+
[ProtocolPhase.COMPRESS, agent.compress],
|
|
588
|
+
[ProtocolPhase.REINTAKE, agent.reintake],
|
|
589
|
+
[ProtocolPhase.GROW, agent.grow],
|
|
590
|
+
[ProtocolPhase.EVOLVE, agent.evolve],
|
|
591
|
+
];
|
|
592
|
+
|
|
593
|
+
let previousData: unknown = { task: task.title, description: task.description };
|
|
594
|
+
const phaseResults: PhaseResult[] = [];
|
|
595
|
+
|
|
596
|
+
for (const [phase, fn] of phases) {
|
|
597
|
+
const result = await runPhaseWithControls(agent, phase, fn, previousData);
|
|
598
|
+
phaseResults.push(result);
|
|
599
|
+
|
|
600
|
+
if (cancelRequested && result.status === 'skipped') {
|
|
601
|
+
// Fill remaining phases as skipped
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
previousData = result.data;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const hasFailed = phaseResults.some(p => p.status === 'failure');
|
|
609
|
+
const wasCancelled = cancelRequested;
|
|
610
|
+
|
|
611
|
+
status = wasCancelled ? 'cancelled' : (hasFailed ? 'error' : 'idle');
|
|
612
|
+
|
|
613
|
+
return {
|
|
614
|
+
cycleId,
|
|
615
|
+
task: task.title,
|
|
616
|
+
domain: agent.identity.domain,
|
|
617
|
+
phases: phaseResults,
|
|
618
|
+
status: wasCancelled ? 'partial' : (hasFailed ? 'partial' : 'complete'),
|
|
619
|
+
totalDurationMs: Date.now() - startedAt,
|
|
620
|
+
startedAt,
|
|
621
|
+
completedAt: Date.now(),
|
|
622
|
+
};
|
|
623
|
+
} catch (err) {
|
|
624
|
+
status = 'error';
|
|
625
|
+
throw err;
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
|
|
629
|
+
pause() {
|
|
630
|
+
if (status === 'running') {
|
|
631
|
+
pauseRequested = true;
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
|
|
635
|
+
resume() {
|
|
636
|
+
if (status === 'paused' || pauseRequested) {
|
|
637
|
+
pauseRequested = false;
|
|
638
|
+
if (pauseResolver) {
|
|
639
|
+
pauseResolver();
|
|
640
|
+
pauseResolver = null;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
|
|
645
|
+
cancel() {
|
|
646
|
+
cancelRequested = true;
|
|
647
|
+
// Also resume if paused so the cancel can take effect
|
|
648
|
+
if (pauseRequested || status === 'paused') {
|
|
649
|
+
pauseRequested = false;
|
|
650
|
+
if (pauseResolver) {
|
|
651
|
+
pauseResolver();
|
|
652
|
+
pauseResolver = null;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
|
|
657
|
+
reset() {
|
|
658
|
+
if (status === 'running') {
|
|
659
|
+
throw new Error('Cannot reset while running. Cancel first.');
|
|
660
|
+
}
|
|
661
|
+
status = 'idle';
|
|
662
|
+
phaseHistory.length = 0;
|
|
663
|
+
pauseRequested = false;
|
|
664
|
+
cancelRequested = false;
|
|
665
|
+
pauseResolver = null;
|
|
666
|
+
},
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
return handle;
|
|
670
|
+
}
|