@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
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { EpisodicEvent } from './MemoryScorer';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SemanticClusterer
|
|
5
|
+
*
|
|
6
|
+
* Compresses raw temporal Episodic buffers into distilled arrays.
|
|
7
|
+
* Native distillation drops repeating trivial structures mapping them into aggregated
|
|
8
|
+
* density nodes explicitly reducing database storage loads across vector boundaries.
|
|
9
|
+
*/
|
|
10
|
+
export class SemanticClusterer {
|
|
11
|
+
/**
|
|
12
|
+
* Actively squash sequentially repeating abstract patterns mapping out semantic arrays.
|
|
13
|
+
*/
|
|
14
|
+
static distill(events: EpisodicEvent[]): EpisodicEvent[] {
|
|
15
|
+
if (events.length === 0) return [];
|
|
16
|
+
|
|
17
|
+
const distilled: EpisodicEvent[] = [];
|
|
18
|
+
let currentSequence: EpisodicEvent = { ...events[0] };
|
|
19
|
+
let repetitonCount = 1;
|
|
20
|
+
|
|
21
|
+
for (let i = 1; i < events.length; i++) {
|
|
22
|
+
const ev = events[i];
|
|
23
|
+
|
|
24
|
+
// If the Action and Target align, we squash them and increment the density metrics
|
|
25
|
+
if (this.isSimilar(currentSequence, ev)) {
|
|
26
|
+
repetitonCount++;
|
|
27
|
+
currentSequence.outcome = `Repeated action successfully (${repetitonCount} times)`;
|
|
28
|
+
|
|
29
|
+
// Track total time span passed over the squash boundary
|
|
30
|
+
if (!currentSequence.context.timeSpanStarted) {
|
|
31
|
+
currentSequence.context.timeSpanStarted = currentSequence.timestamp;
|
|
32
|
+
}
|
|
33
|
+
currentSequence.context.timeSpanEnded = ev.timestamp;
|
|
34
|
+
} else {
|
|
35
|
+
// Similarity broken. Push distilled sequence array and begin anew.
|
|
36
|
+
if (repetitonCount > 1) {
|
|
37
|
+
currentSequence.action = `${currentSequence.action}_Aggregated`;
|
|
38
|
+
}
|
|
39
|
+
distilled.push({ ...currentSequence });
|
|
40
|
+
|
|
41
|
+
currentSequence = { ...ev };
|
|
42
|
+
repetitonCount = 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Push final buffer
|
|
47
|
+
if (repetitonCount > 1) {
|
|
48
|
+
currentSequence.action = `${currentSequence.action}_Aggregated`;
|
|
49
|
+
}
|
|
50
|
+
distilled.push(currentSequence);
|
|
51
|
+
|
|
52
|
+
return distilled;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Determines heuristic thresholds to squash logic natively offline without LLM.
|
|
57
|
+
*/
|
|
58
|
+
private static isSimilar(a: EpisodicEvent, b: EpisodicEvent): boolean {
|
|
59
|
+
if (a.action !== b.action) return false;
|
|
60
|
+
|
|
61
|
+
const aTarget = a.context?.target || a.context?.location;
|
|
62
|
+
const bTarget = b.context?.target || b.context?.location;
|
|
63
|
+
|
|
64
|
+
return aTarget === bTarget;
|
|
65
|
+
}
|
|
66
|
+
}
|
package/src/llm/llm-adapter.ts
CHANGED
|
@@ -49,11 +49,16 @@ async function callAnthropic(
|
|
|
49
49
|
const apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY;
|
|
50
50
|
if (!apiKey) throw new Error('ANTHROPIC_API_KEY required');
|
|
51
51
|
|
|
52
|
-
const system = messages
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
const system = messages
|
|
53
|
+
.filter((m) => m.role === 'system')
|
|
54
|
+
.map((m) => m.content)
|
|
55
|
+
.join('\n');
|
|
56
|
+
const userMessages = messages
|
|
57
|
+
.filter((m) => m.role !== 'system')
|
|
58
|
+
.map((m) => ({
|
|
59
|
+
role: m.role as 'user' | 'assistant',
|
|
60
|
+
content: m.content,
|
|
61
|
+
}));
|
|
57
62
|
|
|
58
63
|
const res = await fetch('https://api.anthropic.com/v1/messages', {
|
|
59
64
|
method: 'POST',
|
|
@@ -73,7 +78,10 @@ async function callAnthropic(
|
|
|
73
78
|
});
|
|
74
79
|
|
|
75
80
|
if (!res.ok) throw new Error(`Anthropic API error: ${res.status}`);
|
|
76
|
-
const data = await res.json() as {
|
|
81
|
+
const data = (await res.json()) as {
|
|
82
|
+
content: Array<{ text: string }>;
|
|
83
|
+
usage?: { output_tokens: number };
|
|
84
|
+
};
|
|
77
85
|
|
|
78
86
|
return {
|
|
79
87
|
content: data.content?.[0]?.text || '',
|
|
@@ -105,13 +113,16 @@ async function callOpenAICompatible(
|
|
|
105
113
|
model: config.model,
|
|
106
114
|
max_tokens: maxTokens,
|
|
107
115
|
temperature,
|
|
108
|
-
messages: messages.map(m => ({ role: m.role, content: m.content })),
|
|
116
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
109
117
|
}),
|
|
110
118
|
signal: AbortSignal.timeout(60_000),
|
|
111
119
|
});
|
|
112
120
|
|
|
113
121
|
if (!res.ok) throw new Error(`${config.provider} API error: ${res.status}`);
|
|
114
|
-
const data = await res.json() as {
|
|
122
|
+
const data = (await res.json()) as {
|
|
123
|
+
choices: Array<{ message: { content: string } }>;
|
|
124
|
+
usage?: { completion_tokens: number };
|
|
125
|
+
};
|
|
115
126
|
|
|
116
127
|
return {
|
|
117
128
|
content: data.choices?.[0]?.message?.content || '',
|
|
@@ -142,13 +153,16 @@ async function callOpenRouter(
|
|
|
142
153
|
model: config.model,
|
|
143
154
|
max_tokens: maxTokens,
|
|
144
155
|
temperature,
|
|
145
|
-
messages: messages.map(m => ({ role: m.role, content: m.content })),
|
|
156
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
146
157
|
}),
|
|
147
158
|
signal: AbortSignal.timeout(60_000),
|
|
148
159
|
});
|
|
149
160
|
|
|
150
161
|
if (!res.ok) throw new Error(`OpenRouter API error: ${res.status}`);
|
|
151
|
-
const data = await res.json() as {
|
|
162
|
+
const data = (await res.json()) as {
|
|
163
|
+
choices: Array<{ message: { content: string } }>;
|
|
164
|
+
usage?: { completion_tokens: number };
|
|
165
|
+
};
|
|
152
166
|
|
|
153
167
|
return {
|
|
154
168
|
content: data.choices?.[0]?.message?.content || '',
|
package/src/mesh/index.ts
CHANGED
|
@@ -47,9 +47,15 @@ export class MeshDiscovery {
|
|
|
47
47
|
return false;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
getPeers(): PeerMetadata[] {
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
getPeers(): PeerMetadata[] {
|
|
51
|
+
return [...this.peers.values()];
|
|
52
|
+
}
|
|
53
|
+
getPeer(id: string): PeerMetadata | undefined {
|
|
54
|
+
return this.peers.get(id);
|
|
55
|
+
}
|
|
56
|
+
getPeerCount(): number {
|
|
57
|
+
return this.peers.size;
|
|
58
|
+
}
|
|
53
59
|
|
|
54
60
|
pruneStalePeers(timeoutMs: number = 15000): number {
|
|
55
61
|
const now = Date.now();
|
|
@@ -97,7 +103,10 @@ export class SignalService {
|
|
|
97
103
|
this.nodeId = nodeId ?? `node-${Date.now().toString(36)}`;
|
|
98
104
|
}
|
|
99
105
|
|
|
100
|
-
broadcastSignal(
|
|
106
|
+
broadcastSignal(
|
|
107
|
+
signal: Omit<MeshSignal, 'nodeId' | 'expiresAt'>,
|
|
108
|
+
ttlMs: number = 3600000
|
|
109
|
+
): MeshSignal {
|
|
101
110
|
const full: MeshSignal = { ...signal, nodeId: this.nodeId, expiresAt: Date.now() + ttlMs };
|
|
102
111
|
this.localSignals.set(`${full.type}:${full.nodeId}`, full);
|
|
103
112
|
return full;
|
|
@@ -112,13 +121,14 @@ export class SignalService {
|
|
|
112
121
|
for (const [key, sig] of this.remoteSignals) {
|
|
113
122
|
if (sig.expiresAt < now) this.remoteSignals.delete(key);
|
|
114
123
|
}
|
|
115
|
-
return [
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
].filter((s) => s.type === type);
|
|
124
|
+
return [...this.remoteSignals.values(), ...this.localSignals.values()].filter(
|
|
125
|
+
(s) => s.type === type
|
|
126
|
+
);
|
|
119
127
|
}
|
|
120
128
|
|
|
121
|
-
getLocalSignals(): MeshSignal[] {
|
|
129
|
+
getLocalSignals(): MeshSignal[] {
|
|
130
|
+
return [...this.localSignals.values()];
|
|
131
|
+
}
|
|
122
132
|
}
|
|
123
133
|
|
|
124
134
|
// =============================================================================
|
|
@@ -160,8 +170,12 @@ export class GossipProtocol {
|
|
|
160
170
|
return absorbed;
|
|
161
171
|
}
|
|
162
172
|
|
|
163
|
-
getPool(): Map<string, GossipPacket> {
|
|
164
|
-
|
|
173
|
+
getPool(): Map<string, GossipPacket> {
|
|
174
|
+
return new Map(this.pool);
|
|
175
|
+
}
|
|
176
|
+
getPoolSize(): number {
|
|
177
|
+
return this.pool.size;
|
|
178
|
+
}
|
|
165
179
|
}
|
|
166
180
|
|
|
167
181
|
// =============================================================================
|
|
@@ -194,8 +208,10 @@ export const MCP_TOOL_SCHEMAS: MCPToolSchema[] = [
|
|
|
194
208
|
inputSchema: {
|
|
195
209
|
type: 'object',
|
|
196
210
|
properties: {
|
|
197
|
-
id: { type: 'string' },
|
|
198
|
-
|
|
211
|
+
id: { type: 'string' },
|
|
212
|
+
domain: { type: 'string' },
|
|
213
|
+
problem: { type: 'string' },
|
|
214
|
+
solution: { type: 'string' },
|
|
199
215
|
tags: { type: 'array', items: { type: 'string' } },
|
|
200
216
|
},
|
|
201
217
|
required: ['id', 'domain', 'problem', 'solution'],
|
|
@@ -207,8 +223,10 @@ export const MCP_TOOL_SCHEMAS: MCPToolSchema[] = [
|
|
|
207
223
|
inputSchema: {
|
|
208
224
|
type: 'object',
|
|
209
225
|
properties: {
|
|
210
|
-
id: { type: 'string' },
|
|
211
|
-
|
|
226
|
+
id: { type: 'string' },
|
|
227
|
+
domain: { type: 'string' },
|
|
228
|
+
insight: { type: 'string' },
|
|
229
|
+
context: { type: 'string' },
|
|
212
230
|
},
|
|
213
231
|
required: ['id', 'domain', 'insight'],
|
|
214
232
|
},
|
|
@@ -219,8 +237,10 @@ export const MCP_TOOL_SCHEMAS: MCPToolSchema[] = [
|
|
|
219
237
|
inputSchema: {
|
|
220
238
|
type: 'object',
|
|
221
239
|
properties: {
|
|
222
|
-
id: { type: 'string' },
|
|
223
|
-
|
|
240
|
+
id: { type: 'string' },
|
|
241
|
+
domain: { type: 'string' },
|
|
242
|
+
mistake: { type: 'string' },
|
|
243
|
+
fix: { type: 'string' },
|
|
224
244
|
severity: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
|
|
225
245
|
},
|
|
226
246
|
required: ['id', 'domain', 'mistake', 'fix'],
|
|
@@ -107,7 +107,7 @@ const DOMAIN_GOALS: Record<string, string[]> = {
|
|
|
107
107
|
'Review and refine CI/CD pipeline efficiency',
|
|
108
108
|
'Automate environment provisioning for local scenario tests',
|
|
109
109
|
'Evaluate telemetry logging cardinality and storage costs',
|
|
110
|
-
]
|
|
110
|
+
],
|
|
111
111
|
};
|
|
112
112
|
|
|
113
113
|
// ── GoalSynthesizer ──
|
|
@@ -125,10 +125,7 @@ export class GoalSynthesizer {
|
|
|
125
125
|
* Synthesize goals from context. Uses LLM when available, falls back to heuristics.
|
|
126
126
|
* Returns goals ranked by relevance.
|
|
127
127
|
*/
|
|
128
|
-
async synthesizeMultiple(
|
|
129
|
-
context: GoalContext,
|
|
130
|
-
count = 3
|
|
131
|
-
): Promise<SynthesizedGoal[]> {
|
|
128
|
+
async synthesizeMultiple(context: GoalContext, count = 3): Promise<SynthesizedGoal[]> {
|
|
132
129
|
// Gather knowledge context
|
|
133
130
|
const knowledgeEntries = context.recentKnowledge ?? this.queryKnowledge(context.domain);
|
|
134
131
|
|
|
@@ -148,15 +145,8 @@ export class GoalSynthesizer {
|
|
|
148
145
|
/**
|
|
149
146
|
* Synthesize a single goal. Backward-compatible with the original API.
|
|
150
147
|
*/
|
|
151
|
-
synthesize(
|
|
152
|
-
|
|
153
|
-
source: Goal['source'] = 'autonomous-boredom'
|
|
154
|
-
): Goal {
|
|
155
|
-
const goals = this.synthesizeHeuristic(
|
|
156
|
-
{ domain: agentDomain },
|
|
157
|
-
[],
|
|
158
|
-
1
|
|
159
|
-
);
|
|
148
|
+
synthesize(agentDomain: string = 'general', source: Goal['source'] = 'autonomous-boredom'): Goal {
|
|
149
|
+
const goals = this.synthesizeHeuristic({ domain: agentDomain }, [], 1);
|
|
160
150
|
if (goals.length > 0) {
|
|
161
151
|
return { ...goals[0], source };
|
|
162
152
|
}
|
|
@@ -189,9 +179,10 @@ export class GoalSynthesizer {
|
|
|
189
179
|
knowledge: StoredEntry[],
|
|
190
180
|
count: number
|
|
191
181
|
): Promise<SynthesizedGoal[]> {
|
|
192
|
-
const knowledgeContext =
|
|
193
|
-
|
|
194
|
-
|
|
182
|
+
const knowledgeContext =
|
|
183
|
+
knowledge.length > 0
|
|
184
|
+
? knowledge.map((k) => `[${k.type}] ${k.content}`).join('\n')
|
|
185
|
+
: 'No relevant knowledge entries found.';
|
|
195
186
|
|
|
196
187
|
const recentTasks = context.recentCompletedTasks?.length
|
|
197
188
|
? context.recentCompletedTasks.slice(0, 10).join('\n- ')
|
|
@@ -200,15 +191,15 @@ export class GoalSynthesizer {
|
|
|
200
191
|
const systemPrompt = [
|
|
201
192
|
`You are a goal synthesizer for an autonomous AI agent team.`,
|
|
202
193
|
`The agent "${context.agentName ?? 'unknown'}" operates in the "${context.domain}" domain.`,
|
|
203
|
-
context.capabilities?.length
|
|
204
|
-
? `Agent capabilities: ${context.capabilities.join(', ')}`
|
|
205
|
-
: '',
|
|
194
|
+
context.capabilities?.length ? `Agent capabilities: ${context.capabilities.join(', ')}` : '',
|
|
206
195
|
context.teamName ? `Team: ${context.teamName}` : '',
|
|
207
196
|
``,
|
|
208
197
|
`Your job: propose ${count} actionable goals the agent should pursue autonomously.`,
|
|
209
198
|
`Goals should be specific, achievable, and build on existing knowledge.`,
|
|
210
199
|
`Avoid duplicating recently completed tasks.`,
|
|
211
|
-
]
|
|
200
|
+
]
|
|
201
|
+
.filter(Boolean)
|
|
202
|
+
.join('\n');
|
|
212
203
|
|
|
213
204
|
const userPrompt = [
|
|
214
205
|
`## Knowledge Context`,
|
|
@@ -223,7 +214,9 @@ export class GoalSynthesizer {
|
|
|
223
214
|
`[{"description": "...", "category": "...", "priority": "low|medium|high", "rationale": "...", "estimatedComplexity": 1-5}]`,
|
|
224
215
|
``,
|
|
225
216
|
`Respond with ONLY the JSON array, no markdown fences.`,
|
|
226
|
-
]
|
|
217
|
+
]
|
|
218
|
+
.filter(Boolean)
|
|
219
|
+
.join('\n');
|
|
227
220
|
|
|
228
221
|
const messages: LLMMessage[] = [
|
|
229
222
|
{ role: 'system', content: systemPrompt },
|
|
@@ -238,11 +231,7 @@ export class GoalSynthesizer {
|
|
|
238
231
|
return this.parseLLMGoals(response.content, context, count);
|
|
239
232
|
}
|
|
240
233
|
|
|
241
|
-
private parseLLMGoals(
|
|
242
|
-
content: string,
|
|
243
|
-
context: GoalContext,
|
|
244
|
-
count: number
|
|
245
|
-
): SynthesizedGoal[] {
|
|
234
|
+
private parseLLMGoals(content: string, context: GoalContext, count: number): SynthesizedGoal[] {
|
|
246
235
|
try {
|
|
247
236
|
// Strip markdown fences if present
|
|
248
237
|
const cleaned = content.replace(/```(?:json)?\s*\n?/g, '').trim();
|
|
@@ -265,7 +254,7 @@ export class GoalSynthesizer {
|
|
|
265
254
|
generatedAt: new Date().toISOString(),
|
|
266
255
|
source: 'autonomous-boredom' as const,
|
|
267
256
|
rationale: g.rationale || 'LLM-generated goal based on context',
|
|
268
|
-
relevanceScore: 1 -
|
|
257
|
+
relevanceScore: 1 - i * 0.1, // rank order from LLM
|
|
269
258
|
}));
|
|
270
259
|
} catch {
|
|
271
260
|
return this.synthesizeHeuristic(context, [], count);
|
|
@@ -278,7 +267,7 @@ export class GoalSynthesizer {
|
|
|
278
267
|
count: number
|
|
279
268
|
): SynthesizedGoal[] {
|
|
280
269
|
const completedSet = new Set(
|
|
281
|
-
(context.recentCompletedTasks ?? []).map(t => t.toLowerCase().trim())
|
|
270
|
+
(context.recentCompletedTasks ?? []).map((t) => t.toLowerCase().trim())
|
|
282
271
|
);
|
|
283
272
|
|
|
284
273
|
// Build candidate pool from domain + generic goals
|
|
@@ -287,11 +276,12 @@ export class GoalSynthesizer {
|
|
|
287
276
|
|
|
288
277
|
// If we have knowledge, generate knowledge-derived goals
|
|
289
278
|
const knowledgeGoals = knowledge
|
|
290
|
-
.filter(k => k.type === 'gotcha')
|
|
291
|
-
.map(k => `Investigate and resolve: ${k.content.slice(0, 120)}`);
|
|
279
|
+
.filter((k) => k.type === 'gotcha')
|
|
280
|
+
.map((k) => `Investigate and resolve: ${k.content.slice(0, 120)}`);
|
|
292
281
|
|
|
293
|
-
const allCandidates = [...knowledgeGoals, ...candidates]
|
|
294
|
-
|
|
282
|
+
const allCandidates = [...knowledgeGoals, ...candidates].filter(
|
|
283
|
+
(desc) => !completedSet.has(desc.toLowerCase().trim())
|
|
284
|
+
);
|
|
295
285
|
|
|
296
286
|
// Shuffle and pick
|
|
297
287
|
const shuffled = allCandidates.sort(() => Math.random() - 0.5);
|
|
@@ -308,7 +298,7 @@ export class GoalSynthesizer {
|
|
|
308
298
|
rationale: knowledgeGoals.includes(description)
|
|
309
299
|
? 'Derived from knowledge store gotcha entries'
|
|
310
300
|
: `Heuristic goal for ${context.domain} domain`,
|
|
311
|
-
relevanceScore: Math.max(0.3, 1 -
|
|
301
|
+
relevanceScore: Math.max(0.3, 1 - i * 0.2),
|
|
312
302
|
}));
|
|
313
303
|
}
|
|
314
304
|
}
|
|
@@ -117,22 +117,48 @@ export interface ServiceConfig {
|
|
|
117
117
|
export type PWGSeverity = 'low' | 'medium' | 'high' | 'critical';
|
|
118
118
|
|
|
119
119
|
export interface Pattern {
|
|
120
|
-
id: string;
|
|
120
|
+
id: string;
|
|
121
|
+
domain: string;
|
|
122
|
+
problem: string;
|
|
123
|
+
solution: string;
|
|
124
|
+
context?: string;
|
|
125
|
+
tags: string[];
|
|
126
|
+
confidence: number;
|
|
127
|
+
createdAt: number;
|
|
128
|
+
updatedAt: number;
|
|
121
129
|
}
|
|
122
130
|
|
|
123
131
|
export interface Wisdom {
|
|
124
|
-
id: string;
|
|
132
|
+
id: string;
|
|
133
|
+
domain: string;
|
|
134
|
+
insight: string;
|
|
135
|
+
context: string;
|
|
136
|
+
source: string;
|
|
137
|
+
tags: string[];
|
|
138
|
+
createdAt: number;
|
|
125
139
|
}
|
|
126
140
|
|
|
127
141
|
export interface Gotcha {
|
|
128
|
-
id: string;
|
|
142
|
+
id: string;
|
|
143
|
+
domain: string;
|
|
144
|
+
mistake: string;
|
|
145
|
+
fix: string;
|
|
146
|
+
severity: PWGSeverity;
|
|
147
|
+
tags: string[];
|
|
148
|
+
createdAt: number;
|
|
129
149
|
}
|
|
130
150
|
|
|
131
151
|
export type PWGEntry = Pattern | Wisdom | Gotcha;
|
|
132
152
|
|
|
133
|
-
export function isPattern(entry: PWGEntry): entry is Pattern {
|
|
134
|
-
|
|
135
|
-
|
|
153
|
+
export function isPattern(entry: PWGEntry): entry is Pattern {
|
|
154
|
+
return entry.id.startsWith('P.');
|
|
155
|
+
}
|
|
156
|
+
export function isWisdom(entry: PWGEntry): entry is Wisdom {
|
|
157
|
+
return entry.id.startsWith('W.');
|
|
158
|
+
}
|
|
159
|
+
export function isGotcha(entry: PWGEntry): entry is Gotcha {
|
|
160
|
+
return entry.id.startsWith('G.');
|
|
161
|
+
}
|
|
136
162
|
|
|
137
163
|
// =============================================================================
|
|
138
164
|
// BASE AGENT — Abstract 7-phase agent contract
|
|
@@ -159,7 +185,10 @@ export abstract class BaseAgent {
|
|
|
159
185
|
/**
|
|
160
186
|
* Execute a complete 7-phase cycle
|
|
161
187
|
*/
|
|
162
|
-
async runCycle(
|
|
188
|
+
async runCycle(
|
|
189
|
+
task: string,
|
|
190
|
+
context: Record<string, unknown> = {}
|
|
191
|
+
): Promise<ProtocolCycleResult> {
|
|
163
192
|
const startedAt = Date.now();
|
|
164
193
|
const cycleId = `cycle_${startedAt}_${Math.random().toString(36).slice(2, 8)}`;
|
|
165
194
|
const phases: PhaseResult[] = [];
|
|
@@ -191,8 +220,16 @@ export abstract class BaseAgent {
|
|
|
191
220
|
const intakeResult = await runPhase(ProtocolPhase.INTAKE, this.intake, { task, ...context });
|
|
192
221
|
const reflectResult = await runPhase(ProtocolPhase.REFLECT, this.reflect, intakeResult.data);
|
|
193
222
|
const executeResult = await runPhase(ProtocolPhase.EXECUTE, this.execute, reflectResult.data);
|
|
194
|
-
const compressResult = await runPhase(
|
|
195
|
-
|
|
223
|
+
const compressResult = await runPhase(
|
|
224
|
+
ProtocolPhase.COMPRESS,
|
|
225
|
+
this.compress,
|
|
226
|
+
executeResult.data
|
|
227
|
+
);
|
|
228
|
+
const reintakeResult = await runPhase(
|
|
229
|
+
ProtocolPhase.REINTAKE,
|
|
230
|
+
this.reintake,
|
|
231
|
+
compressResult.data
|
|
232
|
+
);
|
|
196
233
|
const growResult = await runPhase(ProtocolPhase.GROW, this.grow, reintakeResult.data);
|
|
197
234
|
await runPhase(ProtocolPhase.EVOLVE, this.evolve, growResult.data);
|
|
198
235
|
|
|
@@ -273,9 +310,15 @@ export abstract class BaseService {
|
|
|
273
310
|
this.metadata.lifecycle = ServiceLifecycle.STOPPED;
|
|
274
311
|
}
|
|
275
312
|
|
|
276
|
-
getMetadata(): ServiceMetadata {
|
|
277
|
-
|
|
278
|
-
|
|
313
|
+
getMetadata(): ServiceMetadata {
|
|
314
|
+
return { ...this.metadata };
|
|
315
|
+
}
|
|
316
|
+
getMetrics(): ServiceMetrics {
|
|
317
|
+
return { ...this.metrics };
|
|
318
|
+
}
|
|
319
|
+
isReady(): boolean {
|
|
320
|
+
return this.metadata.lifecycle === ServiceLifecycle.READY;
|
|
321
|
+
}
|
|
279
322
|
|
|
280
323
|
protected recordRequest(latency: number): void {
|
|
281
324
|
this.metrics.requestCount++;
|
|
@@ -333,16 +376,16 @@ export class ServiceManager {
|
|
|
333
376
|
}
|
|
334
377
|
|
|
335
378
|
health(): ServiceManagerHealth {
|
|
336
|
-
const ready = this.services.filter(s => s.isReady());
|
|
379
|
+
const ready = this.services.filter((s) => s.isReady());
|
|
337
380
|
return {
|
|
338
381
|
totalServices: this.services.length,
|
|
339
382
|
readyCount: ready.length,
|
|
340
383
|
allReady: this.services.length > 0 && ready.length === this.services.length,
|
|
341
|
-
services: this.services.map(s => ({
|
|
384
|
+
services: this.services.map((s) => ({
|
|
342
385
|
name: s.getMetadata().name,
|
|
343
386
|
ready: s.isReady(),
|
|
344
|
-
lifecycle: s.getMetadata().lifecycle
|
|
345
|
-
}))
|
|
387
|
+
lifecycle: s.getMetadata().lifecycle,
|
|
388
|
+
})),
|
|
346
389
|
};
|
|
347
390
|
}
|
|
348
391
|
}
|
|
@@ -406,7 +449,13 @@ export class MicroPhaseDecomposer {
|
|
|
406
449
|
groupIdx = Math.max(groupIdx, (assignedToGroup.get(depId) ?? 0) + 1);
|
|
407
450
|
}
|
|
408
451
|
while (groups.length <= groupIdx) {
|
|
409
|
-
groups.push({
|
|
452
|
+
groups.push({
|
|
453
|
+
id: `group_${groups.length}`,
|
|
454
|
+
name: `Group ${groups.length}`,
|
|
455
|
+
tasks: [],
|
|
456
|
+
parallel: true,
|
|
457
|
+
estimatedDuration: 0,
|
|
458
|
+
});
|
|
410
459
|
}
|
|
411
460
|
groups[groupIdx].tasks.push(task);
|
|
412
461
|
assignedToGroup.set(taskId, groupIdx);
|
|
@@ -419,7 +468,11 @@ export class MicroPhaseDecomposer {
|
|
|
419
468
|
}
|
|
420
469
|
|
|
421
470
|
const seqTime = [...this.nodes.values()].reduce((s, t) => s + t.estimatedDuration, 0);
|
|
422
|
-
return {
|
|
471
|
+
return {
|
|
472
|
+
groups,
|
|
473
|
+
totalEstimatedTime: totalTime,
|
|
474
|
+
parallelizationRatio: seqTime > 0 ? ((seqTime - totalTime) / seqTime) * 100 : 0,
|
|
475
|
+
};
|
|
423
476
|
}
|
|
424
477
|
|
|
425
478
|
async executePlan(plan: ExecutionPlan): Promise<ExecutionResult[]> {
|
|
@@ -432,12 +485,26 @@ export class MicroPhaseDecomposer {
|
|
|
432
485
|
const timeout = task.timeout ?? 30000;
|
|
433
486
|
const result = await Promise.race([
|
|
434
487
|
task.execute(),
|
|
435
|
-
new Promise((_, reject) =>
|
|
488
|
+
new Promise((_, reject) =>
|
|
489
|
+
setTimeout(() => reject(new Error('Task timeout')), timeout)
|
|
490
|
+
),
|
|
436
491
|
]);
|
|
437
|
-
return {
|
|
492
|
+
return {
|
|
493
|
+
taskId: task.id,
|
|
494
|
+
status: 'success' as const,
|
|
495
|
+
duration: Date.now() - start,
|
|
496
|
+
result,
|
|
497
|
+
timestamp: Date.now(),
|
|
498
|
+
};
|
|
438
499
|
} catch (err) {
|
|
439
500
|
const isTimeout = err instanceof Error && err.message === 'Task timeout';
|
|
440
|
-
return {
|
|
501
|
+
return {
|
|
502
|
+
taskId: task.id,
|
|
503
|
+
status: (isTimeout ? 'timeout' : 'failure') as 'timeout' | 'failure',
|
|
504
|
+
duration: Date.now() - start,
|
|
505
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
506
|
+
timestamp: Date.now(),
|
|
507
|
+
};
|
|
441
508
|
}
|
|
442
509
|
})
|
|
443
510
|
);
|
|
@@ -447,7 +514,9 @@ export class MicroPhaseDecomposer {
|
|
|
447
514
|
return results;
|
|
448
515
|
}
|
|
449
516
|
|
|
450
|
-
getHistory(): ExecutionResult[] {
|
|
517
|
+
getHistory(): ExecutionResult[] {
|
|
518
|
+
return [...this.history];
|
|
519
|
+
}
|
|
451
520
|
|
|
452
521
|
reset(): void {
|
|
453
522
|
this.nodes.clear();
|
|
@@ -58,7 +58,10 @@ const DEFAULT_COMPLEXITY_THRESHOLD = 2;
|
|
|
58
58
|
// ── LLM Adapter Interface (injectable for testing) ──
|
|
59
59
|
|
|
60
60
|
export interface LLMAdapter {
|
|
61
|
-
call(
|
|
61
|
+
call(
|
|
62
|
+
messages: LLMMessage[],
|
|
63
|
+
options?: { maxTokens?: number; temperature?: number }
|
|
64
|
+
): Promise<string>;
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
/** Create an LLMAdapter from a ModelConfig */
|
|
@@ -159,7 +162,7 @@ Rules:
|
|
|
159
162
|
this.validatePhases(phases);
|
|
160
163
|
|
|
161
164
|
const sorted = this.topologicalSort(phases);
|
|
162
|
-
const phaseMap = new Map(phases.map(p => [p.id, p]));
|
|
165
|
+
const phaseMap = new Map(phases.map((p) => [p.id, p]));
|
|
163
166
|
const waveAssignment = new Map<string, number>();
|
|
164
167
|
const waves: MicroPhase[][] = [];
|
|
165
168
|
|
|
@@ -181,15 +184,16 @@ Rules:
|
|
|
181
184
|
// Calculate timing
|
|
182
185
|
const sequentialTime = phases.reduce((sum, p) => sum + p.estimatedDuration, 0);
|
|
183
186
|
const parallelTime = waves.reduce((sum, wave) => {
|
|
184
|
-
return sum + Math.max(...wave.map(p => p.estimatedDuration));
|
|
187
|
+
return sum + Math.max(...wave.map((p) => p.estimatedDuration));
|
|
185
188
|
}, 0);
|
|
186
189
|
|
|
187
190
|
return {
|
|
188
191
|
waves,
|
|
189
192
|
totalEstimatedDuration: parallelTime,
|
|
190
|
-
parallelizationRatio:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
+
parallelizationRatio:
|
|
194
|
+
sequentialTime > 0
|
|
195
|
+
? Math.round(((sequentialTime - parallelTime) / sequentialTime) * 100)
|
|
196
|
+
: 0,
|
|
193
197
|
phaseCount: phases.length,
|
|
194
198
|
};
|
|
195
199
|
}
|
|
@@ -212,7 +216,9 @@ Rules:
|
|
|
212
216
|
description: String(p.description ?? 'Unknown phase'),
|
|
213
217
|
dependencies: Array.isArray(p.dependencies) ? p.dependencies.map(String) : [],
|
|
214
218
|
estimatedDuration: typeof p.estimatedDuration === 'number' ? p.estimatedDuration : 5000,
|
|
215
|
-
requiredCapabilities: Array.isArray(p.requiredCapabilities)
|
|
219
|
+
requiredCapabilities: Array.isArray(p.requiredCapabilities)
|
|
220
|
+
? p.requiredCapabilities.map(String)
|
|
221
|
+
: ['coding'],
|
|
216
222
|
}));
|
|
217
223
|
} catch {
|
|
218
224
|
return this.fallbackSinglePhase(taskId);
|
|
@@ -220,17 +226,19 @@ Rules:
|
|
|
220
226
|
}
|
|
221
227
|
|
|
222
228
|
private fallbackSinglePhase(taskId: string): MicroPhase[] {
|
|
223
|
-
return [
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
229
|
+
return [
|
|
230
|
+
{
|
|
231
|
+
id: `${taskId}_single`,
|
|
232
|
+
description: 'Execute task as single unit',
|
|
233
|
+
dependencies: [],
|
|
234
|
+
estimatedDuration: 10000,
|
|
235
|
+
requiredCapabilities: ['coding'],
|
|
236
|
+
},
|
|
237
|
+
];
|
|
230
238
|
}
|
|
231
239
|
|
|
232
240
|
private validatePhases(phases: MicroPhase[]): void {
|
|
233
|
-
const ids = new Set(phases.map(p => p.id));
|
|
241
|
+
const ids = new Set(phases.map((p) => p.id));
|
|
234
242
|
|
|
235
243
|
for (const phase of phases) {
|
|
236
244
|
for (const dep of phase.dependencies) {
|
|
@@ -245,7 +253,7 @@ Rules:
|
|
|
245
253
|
}
|
|
246
254
|
|
|
247
255
|
private topologicalSort(phases: MicroPhase[]): string[] {
|
|
248
|
-
const phaseMap = new Map(phases.map(p => [p.id, p]));
|
|
256
|
+
const phaseMap = new Map(phases.map((p) => [p.id, p]));
|
|
249
257
|
const visited = new Set<string>();
|
|
250
258
|
const inStack = new Set<string>();
|
|
251
259
|
const result: string[] = [];
|
|
@@ -280,7 +288,7 @@ Rules:
|
|
|
280
288
|
private enforceParallelismLimit(phases: MicroPhase[], maxParallelism: number): void {
|
|
281
289
|
// Build initial plan to see wave sizes
|
|
282
290
|
const plan = this.buildExecutionPlan(phases);
|
|
283
|
-
const phaseMap = new Map(phases.map(p => [p.id, p]));
|
|
291
|
+
const phaseMap = new Map(phases.map((p) => [p.id, p]));
|
|
284
292
|
|
|
285
293
|
for (const wave of plan.waves) {
|
|
286
294
|
if (wave.length <= maxParallelism) continue;
|