dino-spec 17.4.2 → 17.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +10 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/core/agents/__tests__/confidence-gate.test.d.ts +5 -0
- package/dist/core/agents/__tests__/confidence-gate.test.d.ts.map +1 -0
- package/dist/core/agents/__tests__/confidence-gate.test.js +329 -0
- package/dist/core/agents/__tests__/confidence-gate.test.js.map +1 -0
- package/dist/core/agents/__tests__/gap-detector.test.d.ts +5 -0
- package/dist/core/agents/__tests__/gap-detector.test.d.ts.map +1 -0
- package/dist/core/agents/__tests__/gap-detector.test.js +609 -0
- package/dist/core/agents/__tests__/gap-detector.test.js.map +1 -0
- package/dist/core/agents/__tests__/learning-loop.test.d.ts +5 -0
- package/dist/core/agents/__tests__/learning-loop.test.d.ts.map +1 -0
- package/dist/core/agents/__tests__/learning-loop.test.js +663 -0
- package/dist/core/agents/__tests__/learning-loop.test.js.map +1 -0
- package/dist/core/agents/__tests__/parallel-executor.test.d.ts +5 -0
- package/dist/core/agents/__tests__/parallel-executor.test.d.ts.map +1 -0
- package/dist/core/agents/__tests__/parallel-executor.test.js +610 -0
- package/dist/core/agents/__tests__/parallel-executor.test.js.map +1 -0
- package/dist/core/agents/__tests__/research-validator.test.js +5 -5
- package/dist/core/agents/__tests__/research-validator.test.js.map +1 -1
- package/dist/core/agents/__tests__/skill-creator.test.d.ts +5 -0
- package/dist/core/agents/__tests__/skill-creator.test.d.ts.map +1 -0
- package/dist/core/agents/__tests__/skill-creator.test.js +443 -0
- package/dist/core/agents/__tests__/skill-creator.test.js.map +1 -0
- package/dist/core/agents/__tests__/state-persistence.test.d.ts +2 -0
- package/dist/core/agents/__tests__/state-persistence.test.d.ts.map +1 -0
- package/dist/core/agents/__tests__/state-persistence.test.js +270 -0
- package/dist/core/agents/__tests__/state-persistence.test.js.map +1 -0
- package/dist/core/agents/__tests__/validation-cache.test.d.ts +2 -0
- package/dist/core/agents/__tests__/validation-cache.test.d.ts.map +1 -0
- package/dist/core/agents/__tests__/validation-cache.test.js +181 -0
- package/dist/core/agents/__tests__/validation-cache.test.js.map +1 -0
- package/dist/core/agents/blackboard.d.ts +22 -3
- package/dist/core/agents/blackboard.d.ts.map +1 -1
- package/dist/core/agents/blackboard.js +52 -2
- package/dist/core/agents/blackboard.js.map +1 -1
- package/dist/core/agents/circuit-breaker.d.ts +79 -1
- package/dist/core/agents/circuit-breaker.d.ts.map +1 -1
- package/dist/core/agents/circuit-breaker.js +175 -1
- package/dist/core/agents/circuit-breaker.js.map +1 -1
- package/dist/core/agents/clarification-phase.d.ts +128 -0
- package/dist/core/agents/clarification-phase.d.ts.map +1 -0
- package/dist/core/agents/clarification-phase.js +375 -0
- package/dist/core/agents/clarification-phase.js.map +1 -0
- package/dist/core/agents/confidence-gate.d.ts +116 -3
- package/dist/core/agents/confidence-gate.d.ts.map +1 -1
- package/dist/core/agents/confidence-gate.js +363 -3
- package/dist/core/agents/confidence-gate.js.map +1 -1
- package/dist/core/agents/correction-tracker.d.ts +197 -0
- package/dist/core/agents/correction-tracker.d.ts.map +1 -0
- package/dist/core/agents/correction-tracker.js +366 -0
- package/dist/core/agents/correction-tracker.js.map +1 -0
- package/dist/core/agents/dependency-graph.d.ts +193 -0
- package/dist/core/agents/dependency-graph.d.ts.map +1 -0
- package/dist/core/agents/dependency-graph.js +462 -0
- package/dist/core/agents/dependency-graph.js.map +1 -0
- package/dist/core/agents/gap-detector.d.ts +277 -0
- package/dist/core/agents/gap-detector.d.ts.map +1 -0
- package/dist/core/agents/gap-detector.js +540 -0
- package/dist/core/agents/gap-detector.js.map +1 -0
- package/dist/core/agents/index.d.ts +14 -1
- package/dist/core/agents/index.d.ts.map +1 -1
- package/dist/core/agents/index.js +26 -1
- package/dist/core/agents/index.js.map +1 -1
- package/dist/core/agents/message-protocol.d.ts +13 -2
- package/dist/core/agents/message-protocol.d.ts.map +1 -1
- package/dist/core/agents/message-protocol.js +20 -1
- package/dist/core/agents/message-protocol.js.map +1 -1
- package/dist/core/agents/parallel-executor.d.ts +182 -0
- package/dist/core/agents/parallel-executor.d.ts.map +1 -0
- package/dist/core/agents/parallel-executor.js +474 -0
- package/dist/core/agents/parallel-executor.js.map +1 -0
- package/dist/core/agents/pattern-detector.d.ts +157 -0
- package/dist/core/agents/pattern-detector.d.ts.map +1 -0
- package/dist/core/agents/pattern-detector.js +370 -0
- package/dist/core/agents/pattern-detector.js.map +1 -0
- package/dist/core/agents/registry-client.d.ts +6 -0
- package/dist/core/agents/registry-client.d.ts.map +1 -1
- package/dist/core/agents/registry-client.js +3 -0
- package/dist/core/agents/registry-client.js.map +1 -1
- package/dist/core/agents/research-phase.d.ts +114 -0
- package/dist/core/agents/research-phase.d.ts.map +1 -0
- package/dist/core/agents/research-phase.js +355 -0
- package/dist/core/agents/research-phase.js.map +1 -0
- package/dist/core/agents/research-validator.d.ts +13 -2
- package/dist/core/agents/research-validator.d.ts.map +1 -1
- package/dist/core/agents/research-validator.js +63 -31
- package/dist/core/agents/research-validator.js.map +1 -1
- package/dist/core/agents/skill-creator.d.ts +174 -0
- package/dist/core/agents/skill-creator.d.ts.map +1 -0
- package/dist/core/agents/skill-creator.js +570 -0
- package/dist/core/agents/skill-creator.js.map +1 -0
- package/dist/core/agents/state-persistence.d.ts +184 -0
- package/dist/core/agents/state-persistence.d.ts.map +1 -0
- package/dist/core/agents/state-persistence.js +394 -0
- package/dist/core/agents/state-persistence.js.map +1 -0
- package/dist/core/agents/validation-cache.d.ts +122 -0
- package/dist/core/agents/validation-cache.d.ts.map +1 -0
- package/dist/core/agents/validation-cache.js +280 -0
- package/dist/core/agents/validation-cache.js.map +1 -0
- package/dist/core/agents/validators/__tests__/validators.test.d.ts +5 -0
- package/dist/core/agents/validators/__tests__/validators.test.d.ts.map +1 -0
- package/dist/core/agents/validators/__tests__/validators.test.js +321 -0
- package/dist/core/agents/validators/__tests__/validators.test.js.map +1 -0
- package/dist/core/agents/validators/base-validator.d.ts +191 -0
- package/dist/core/agents/validators/base-validator.d.ts.map +1 -0
- package/dist/core/agents/validators/base-validator.js +192 -0
- package/dist/core/agents/validators/base-validator.js.map +1 -0
- package/dist/core/agents/validators/index.d.ts +7 -0
- package/dist/core/agents/validators/index.d.ts.map +1 -0
- package/dist/core/agents/validators/index.js +7 -0
- package/dist/core/agents/validators/index.js.map +1 -0
- package/dist/core/agents/validators/npm-validator.d.ts +50 -0
- package/dist/core/agents/validators/npm-validator.d.ts.map +1 -0
- package/dist/core/agents/validators/npm-validator.js +211 -0
- package/dist/core/agents/validators/npm-validator.js.map +1 -0
- package/dist/core/agents/validators/pip-validator.d.ts +49 -0
- package/dist/core/agents/validators/pip-validator.d.ts.map +1 -0
- package/dist/core/agents/validators/pip-validator.js +191 -0
- package/dist/core/agents/validators/pip-validator.js.map +1 -0
- package/dist/core/agents/validators/validator-registry.d.ts +122 -0
- package/dist/core/agents/validators/validator-registry.d.ts.map +1 -0
- package/dist/core/agents/validators/validator-registry.js +321 -0
- package/dist/core/agents/validators/validator-registry.js.map +1 -0
- package/dist/core/context-repl/types.d.ts +4 -4
- package/dist/core/memory/index.d.ts +1 -0
- package/dist/core/memory/index.d.ts.map +1 -1
- package/dist/core/memory/index.js +2 -0
- package/dist/core/memory/index.js.map +1 -1
- package/dist/core/memory/learning-store.d.ts +222 -0
- package/dist/core/memory/learning-store.d.ts.map +1 -0
- package/dist/core/memory/learning-store.js +477 -0
- package/dist/core/memory/learning-store.js.map +1 -0
- package/dist/core/spec-analyzer/__tests__/ambiguity-detector.test.d.ts +5 -0
- package/dist/core/spec-analyzer/__tests__/ambiguity-detector.test.d.ts.map +1 -0
- package/dist/core/spec-analyzer/__tests__/ambiguity-detector.test.js +401 -0
- package/dist/core/spec-analyzer/__tests__/ambiguity-detector.test.js.map +1 -0
- package/dist/core/spec-analyzer/ambiguity-detector.d.ts +99 -0
- package/dist/core/spec-analyzer/ambiguity-detector.d.ts.map +1 -0
- package/dist/core/spec-analyzer/ambiguity-detector.js +250 -0
- package/dist/core/spec-analyzer/ambiguity-detector.js.map +1 -0
- package/dist/core/spec-analyzer/clarification-generator.d.ts +76 -0
- package/dist/core/spec-analyzer/clarification-generator.d.ts.map +1 -0
- package/dist/core/spec-analyzer/clarification-generator.js +257 -0
- package/dist/core/spec-analyzer/clarification-generator.js.map +1 -0
- package/dist/core/spec-analyzer/index.d.ts +10 -1
- package/dist/core/spec-analyzer/index.d.ts.map +1 -1
- package/dist/core/spec-analyzer/index.js +13 -1
- package/dist/core/spec-analyzer/index.js.map +1 -1
- package/dist/core/spec-analyzer/patterns.d.ts +73 -0
- package/dist/core/spec-analyzer/patterns.d.ts.map +1 -0
- package/dist/core/spec-analyzer/patterns.js +412 -0
- package/dist/core/spec-analyzer/patterns.js.map +1 -0
- package/dist/hooks/__tests__/dynamic-generator.test.d.ts +5 -0
- package/dist/hooks/__tests__/dynamic-generator.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/dynamic-generator.test.js +425 -0
- package/dist/hooks/__tests__/dynamic-generator.test.js.map +1 -0
- package/dist/hooks/__tests__/hook-agent-bridge.test.d.ts +5 -0
- package/dist/hooks/__tests__/hook-agent-bridge.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/hook-agent-bridge.test.js +315 -0
- package/dist/hooks/__tests__/hook-agent-bridge.test.js.map +1 -0
- package/dist/hooks/dynamic-generator.d.ts +158 -0
- package/dist/hooks/dynamic-generator.d.ts.map +1 -0
- package/dist/hooks/dynamic-generator.js +448 -0
- package/dist/hooks/dynamic-generator.js.map +1 -0
- package/dist/hooks/hook-agent-bridge.d.ts +252 -0
- package/dist/hooks/hook-agent-bridge.d.ts.map +1 -0
- package/dist/hooks/hook-agent-bridge.js +489 -0
- package/dist/hooks/hook-agent-bridge.js.map +1 -0
- package/dist/hooks/index.d.ts +3 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +5 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/mcp/tool-catalog.d.ts.map +1 -1
- package/dist/mcp/tool-catalog.js +47 -0
- package/dist/mcp/tool-catalog.js.map +1 -1
- package/dist/mcp/tool-tiers.d.ts.map +1 -1
- package/dist/mcp/tool-tiers.js +4 -0
- package/dist/mcp/tool-tiers.js.map +1 -1
- package/dist/mcp/tools/index.d.ts +2 -1
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +15 -1
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/learning-store.d.ts +30 -0
- package/dist/mcp/tools/learning-store.d.ts.map +1 -0
- package/dist/mcp/tools/learning-store.js +286 -0
- package/dist/mcp/tools/learning-store.js.map +1 -0
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +2 -47
- package/dist/rules/index.js.map +1 -1
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +159 -38
- package/dist/skills/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
4
|
+
import { DEFAULT_PERSISTENCE_CONFIG, StatePersistence, } from '../state-persistence.js';
|
|
5
|
+
describe('StatePersistence', () => {
|
|
6
|
+
const testBaseDir = '.dino/test-agent-state';
|
|
7
|
+
let persistence;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
// Clean up test directory
|
|
10
|
+
if (existsSync(testBaseDir)) {
|
|
11
|
+
rmSync(testBaseDir, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
persistence = new StatePersistence({ baseDir: testBaseDir });
|
|
14
|
+
});
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
persistence.dispose();
|
|
17
|
+
if (existsSync(testBaseDir)) {
|
|
18
|
+
rmSync(testBaseDir, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
describe('Claims Persistence', () => {
|
|
22
|
+
it('should save and load claims', () => {
|
|
23
|
+
const claims = [
|
|
24
|
+
{
|
|
25
|
+
resource: 'src/file1.ts',
|
|
26
|
+
agentId: 'agent-1',
|
|
27
|
+
claimedAt: new Date().toISOString(),
|
|
28
|
+
expiresAt: new Date(Date.now() + 3600000).toISOString(),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
resource: 'src/file2.ts',
|
|
32
|
+
agentId: 'agent-2',
|
|
33
|
+
claimedAt: new Date().toISOString(),
|
|
34
|
+
expiresAt: new Date(Date.now() + 3600000).toISOString(),
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
persistence.saveClaims(claims);
|
|
38
|
+
const loaded = persistence.loadClaims();
|
|
39
|
+
expect(loaded).toHaveLength(2);
|
|
40
|
+
expect(loaded[0].resource).toBe('src/file1.ts');
|
|
41
|
+
expect(loaded[1].resource).toBe('src/file2.ts');
|
|
42
|
+
});
|
|
43
|
+
it('should filter out stale claims (> 1 hour)', () => {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
const claims = [
|
|
46
|
+
{
|
|
47
|
+
resource: 'src/fresh.ts',
|
|
48
|
+
agentId: 'agent-1',
|
|
49
|
+
claimedAt: new Date(now - 1000).toISOString(), // 1 second ago
|
|
50
|
+
expiresAt: new Date(now + 3600000).toISOString(),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
resource: 'src/stale.ts',
|
|
54
|
+
agentId: 'agent-2',
|
|
55
|
+
claimedAt: new Date(now - 3700000).toISOString(), // Over 1 hour ago
|
|
56
|
+
expiresAt: new Date(now - 100000).toISOString(), // Already expired
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
persistence.saveClaims(claims);
|
|
60
|
+
const loaded = persistence.loadClaims();
|
|
61
|
+
expect(loaded).toHaveLength(1);
|
|
62
|
+
expect(loaded[0].resource).toBe('src/fresh.ts');
|
|
63
|
+
});
|
|
64
|
+
it('should handle empty claims file', () => {
|
|
65
|
+
const loaded = persistence.loadClaims();
|
|
66
|
+
expect(loaded).toHaveLength(0);
|
|
67
|
+
});
|
|
68
|
+
it('should handle corrupted claims file', () => {
|
|
69
|
+
mkdirSync(testBaseDir, { recursive: true });
|
|
70
|
+
writeFileSync(join(testBaseDir, 'claims.json'), 'invalid json');
|
|
71
|
+
const loaded = persistence.loadClaims();
|
|
72
|
+
expect(loaded).toHaveLength(0);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('Message History Persistence', () => {
|
|
76
|
+
it('should save and load message history', () => {
|
|
77
|
+
const messages = [
|
|
78
|
+
{
|
|
79
|
+
id: 'msg-1',
|
|
80
|
+
from: 'agent-1',
|
|
81
|
+
to: 'agent-2',
|
|
82
|
+
type: 'query',
|
|
83
|
+
payload: { queryType: 'file-content', resource: 'test.ts' },
|
|
84
|
+
timestamp: new Date().toISOString(),
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: 'msg-2',
|
|
88
|
+
from: 'agent-2',
|
|
89
|
+
to: 'agent-1',
|
|
90
|
+
type: 'response',
|
|
91
|
+
payload: { queryId: 'msg-1', success: true, data: 'content' },
|
|
92
|
+
timestamp: new Date().toISOString(),
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
persistence.saveMessageHistory(messages);
|
|
96
|
+
const loaded = persistence.loadMessageHistory();
|
|
97
|
+
expect(loaded).toHaveLength(2);
|
|
98
|
+
expect(loaded[0].id).toBe('msg-1');
|
|
99
|
+
expect(loaded[1].id).toBe('msg-2');
|
|
100
|
+
});
|
|
101
|
+
it('should append messages incrementally', () => {
|
|
102
|
+
const message1 = {
|
|
103
|
+
id: 'msg-1',
|
|
104
|
+
from: 'agent-1',
|
|
105
|
+
to: null,
|
|
106
|
+
type: 'broadcast',
|
|
107
|
+
payload: { broadcastType: 'file-read', resource: 'test.ts' },
|
|
108
|
+
timestamp: new Date().toISOString(),
|
|
109
|
+
};
|
|
110
|
+
const message2 = {
|
|
111
|
+
id: 'msg-2',
|
|
112
|
+
from: 'agent-2',
|
|
113
|
+
to: null,
|
|
114
|
+
type: 'broadcast',
|
|
115
|
+
payload: { broadcastType: 'task-complete' },
|
|
116
|
+
timestamp: new Date().toISOString(),
|
|
117
|
+
};
|
|
118
|
+
persistence.appendMessage(message1);
|
|
119
|
+
persistence.appendMessage(message2);
|
|
120
|
+
persistence.flushMessages();
|
|
121
|
+
const loaded = persistence.loadMessageHistory();
|
|
122
|
+
expect(loaded).toHaveLength(2);
|
|
123
|
+
});
|
|
124
|
+
it('should compress history when exceeding max size', () => {
|
|
125
|
+
const smallPersistence = new StatePersistence({
|
|
126
|
+
baseDir: testBaseDir,
|
|
127
|
+
maxActiveMessages: 5,
|
|
128
|
+
});
|
|
129
|
+
// Create 10 messages
|
|
130
|
+
const messages = [];
|
|
131
|
+
for (let i = 0; i < 10; i++) {
|
|
132
|
+
messages.push({
|
|
133
|
+
id: `msg-${i}`,
|
|
134
|
+
from: 'agent-1',
|
|
135
|
+
to: null,
|
|
136
|
+
type: 'broadcast',
|
|
137
|
+
payload: { broadcastType: 'custom', data: { index: i } },
|
|
138
|
+
timestamp: new Date().toISOString(),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
smallPersistence.saveMessageHistory(messages);
|
|
142
|
+
const loaded = smallPersistence.loadMessageHistory();
|
|
143
|
+
// Should only have last 5 messages
|
|
144
|
+
expect(loaded).toHaveLength(5);
|
|
145
|
+
expect(loaded[0].id).toBe('msg-5');
|
|
146
|
+
expect(loaded[4].id).toBe('msg-9');
|
|
147
|
+
smallPersistence.dispose();
|
|
148
|
+
});
|
|
149
|
+
it('should handle empty messages file', () => {
|
|
150
|
+
const loaded = persistence.loadMessageHistory();
|
|
151
|
+
expect(loaded).toHaveLength(0);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
describe('Shared State Persistence', () => {
|
|
155
|
+
it('should save and load shared state', () => {
|
|
156
|
+
const state = new Map();
|
|
157
|
+
state.set('key1', 'value1');
|
|
158
|
+
state.set('key2', { nested: 'object' });
|
|
159
|
+
state.set('key3', [1, 2, 3]);
|
|
160
|
+
persistence.saveSharedState(state);
|
|
161
|
+
const loaded = persistence.loadSharedState();
|
|
162
|
+
expect(loaded.get('key1')).toBe('value1');
|
|
163
|
+
expect(loaded.get('key2')).toEqual({ nested: 'object' });
|
|
164
|
+
expect(loaded.get('key3')).toEqual([1, 2, 3]);
|
|
165
|
+
});
|
|
166
|
+
it('should handle empty state file', () => {
|
|
167
|
+
const loaded = persistence.loadSharedState();
|
|
168
|
+
expect(loaded.size).toBe(0);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe('Full State Management', () => {
|
|
172
|
+
it('should load all state at once', () => {
|
|
173
|
+
// Save some data first
|
|
174
|
+
const claims = [
|
|
175
|
+
{
|
|
176
|
+
resource: 'test.ts',
|
|
177
|
+
agentId: 'agent-1',
|
|
178
|
+
claimedAt: new Date().toISOString(),
|
|
179
|
+
},
|
|
180
|
+
];
|
|
181
|
+
const messages = [
|
|
182
|
+
{
|
|
183
|
+
id: 'msg-1',
|
|
184
|
+
from: 'agent-1',
|
|
185
|
+
to: null,
|
|
186
|
+
type: 'broadcast',
|
|
187
|
+
payload: { broadcastType: 'custom' },
|
|
188
|
+
timestamp: new Date().toISOString(),
|
|
189
|
+
},
|
|
190
|
+
];
|
|
191
|
+
const state = new Map();
|
|
192
|
+
state.set('testKey', 'testValue');
|
|
193
|
+
persistence.saveClaims(claims);
|
|
194
|
+
persistence.saveMessageHistory(messages);
|
|
195
|
+
persistence.saveSharedState(state);
|
|
196
|
+
// Load all at once
|
|
197
|
+
const { claims: loadedClaims, messages: loadedMessages, sharedState } = persistence.loadAll();
|
|
198
|
+
expect(loadedClaims).toHaveLength(1);
|
|
199
|
+
expect(loadedMessages).toHaveLength(1);
|
|
200
|
+
expect(sharedState.get('testKey')).toBe('testValue');
|
|
201
|
+
});
|
|
202
|
+
it('should save all state at once', () => {
|
|
203
|
+
const claims = [
|
|
204
|
+
{
|
|
205
|
+
resource: 'all.ts',
|
|
206
|
+
agentId: 'agent-all',
|
|
207
|
+
claimedAt: new Date().toISOString(),
|
|
208
|
+
},
|
|
209
|
+
];
|
|
210
|
+
const messages = [
|
|
211
|
+
{
|
|
212
|
+
id: 'msg-all',
|
|
213
|
+
from: 'agent-all',
|
|
214
|
+
to: null,
|
|
215
|
+
type: 'broadcast',
|
|
216
|
+
payload: { broadcastType: 'custom' },
|
|
217
|
+
timestamp: new Date().toISOString(),
|
|
218
|
+
},
|
|
219
|
+
];
|
|
220
|
+
const state = new Map();
|
|
221
|
+
state.set('allKey', 'allValue');
|
|
222
|
+
persistence.saveAll(claims, messages, state);
|
|
223
|
+
// Verify by loading back
|
|
224
|
+
const loaded = persistence.loadAll();
|
|
225
|
+
expect(loaded.claims).toHaveLength(1);
|
|
226
|
+
expect(loaded.claims[0].resource).toBe('all.ts');
|
|
227
|
+
expect(loaded.messages).toHaveLength(1);
|
|
228
|
+
expect(loaded.sharedState.get('allKey')).toBe('allValue');
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
describe('Cleanup', () => {
|
|
232
|
+
it('should clean up stale claims', () => {
|
|
233
|
+
const now = Date.now();
|
|
234
|
+
const claims = [
|
|
235
|
+
{
|
|
236
|
+
resource: 'fresh.ts',
|
|
237
|
+
agentId: 'agent-1',
|
|
238
|
+
claimedAt: new Date(now - 1000).toISOString(),
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
resource: 'old.ts',
|
|
242
|
+
agentId: 'agent-2',
|
|
243
|
+
claimedAt: new Date(now - 7200000).toISOString(), // 2 hours ago
|
|
244
|
+
},
|
|
245
|
+
];
|
|
246
|
+
const cleaned = persistence.cleanupStaleClaims(claims);
|
|
247
|
+
expect(cleaned).toHaveLength(1);
|
|
248
|
+
expect(cleaned[0].resource).toBe('fresh.ts');
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
describe('Configuration', () => {
|
|
252
|
+
it('should use default configuration', () => {
|
|
253
|
+
expect(DEFAULT_PERSISTENCE_CONFIG.baseDir).toBe('.dino/agent-state');
|
|
254
|
+
expect(DEFAULT_PERSISTENCE_CONFIG.maxActiveMessages).toBe(1000);
|
|
255
|
+
expect(DEFAULT_PERSISTENCE_CONFIG.maxClaimAgeMs).toBe(3600000); // 1 hour
|
|
256
|
+
});
|
|
257
|
+
it('should allow custom configuration', () => {
|
|
258
|
+
const customConfig = {
|
|
259
|
+
baseDir: 'custom/path',
|
|
260
|
+
maxActiveMessages: 500,
|
|
261
|
+
maxClaimAgeMs: 1800000, // 30 minutes
|
|
262
|
+
};
|
|
263
|
+
const customPersistence = new StatePersistence(customConfig);
|
|
264
|
+
// Handle both Windows and Unix path separators
|
|
265
|
+
expect(customPersistence.claimsPath).toMatch(/custom[/\\]path/);
|
|
266
|
+
customPersistence.dispose();
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
//# sourceMappingURL=state-persistence.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-persistence.test.js","sourceRoot":"","sources":["../../../../src/core/agents/__tests__/state-persistence.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-cache.test.d.ts","sourceRoot":"","sources":["../../../../src/core/agents/__tests__/validation-cache.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { API_RATE_LIMITS, RateLimiter, rateLimited, rateLimiter, ValidationCache, withRateLimit, } from '../validation-cache.js';
|
|
3
|
+
describe('ValidationCache', () => {
|
|
4
|
+
let cache;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
cache = new ValidationCache({ ttlMs: 1000, maxEntries: 5 });
|
|
7
|
+
});
|
|
8
|
+
describe('Basic Operations', () => {
|
|
9
|
+
it('should store and retrieve values', () => {
|
|
10
|
+
cache.set('key1', 'value1');
|
|
11
|
+
expect(cache.get('key1')).toBe('value1');
|
|
12
|
+
});
|
|
13
|
+
it('should return undefined for missing keys', () => {
|
|
14
|
+
expect(cache.get('nonexistent')).toBeUndefined();
|
|
15
|
+
});
|
|
16
|
+
it('should check if key exists', () => {
|
|
17
|
+
cache.set('key1', 'value1');
|
|
18
|
+
expect(cache.has('key1')).toBe(true);
|
|
19
|
+
expect(cache.has('nonexistent')).toBe(false);
|
|
20
|
+
});
|
|
21
|
+
it('should delete values', () => {
|
|
22
|
+
cache.set('key1', 'value1');
|
|
23
|
+
expect(cache.delete('key1')).toBe(true);
|
|
24
|
+
expect(cache.get('key1')).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
it('should clear all values', () => {
|
|
27
|
+
cache.set('key1', 'value1');
|
|
28
|
+
cache.set('key2', 'value2');
|
|
29
|
+
cache.clear();
|
|
30
|
+
expect(cache.get('key1')).toBeUndefined();
|
|
31
|
+
expect(cache.get('key2')).toBeUndefined();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe('TTL Expiration', () => {
|
|
35
|
+
it('should expire entries after TTL', async () => {
|
|
36
|
+
const shortCache = new ValidationCache({ ttlMs: 50 });
|
|
37
|
+
shortCache.set('key1', 'value1');
|
|
38
|
+
expect(shortCache.get('key1')).toBe('value1');
|
|
39
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
40
|
+
expect(shortCache.get('key1')).toBeUndefined();
|
|
41
|
+
});
|
|
42
|
+
it('should allow custom TTL per entry', async () => {
|
|
43
|
+
cache.set('short', 'value', 50);
|
|
44
|
+
cache.set('long', 'value', 5000);
|
|
45
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
46
|
+
expect(cache.get('short')).toBeUndefined();
|
|
47
|
+
expect(cache.get('long')).toBe('value');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('Max Entries', () => {
|
|
51
|
+
it('should evict oldest entry when at capacity', () => {
|
|
52
|
+
for (let i = 0; i < 6; i++) {
|
|
53
|
+
cache.set(`key${i}`, `value${i}`);
|
|
54
|
+
}
|
|
55
|
+
// First entry should be evicted
|
|
56
|
+
const stats = cache.getStats();
|
|
57
|
+
expect(stats.size).toBeLessThanOrEqual(5);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('Statistics', () => {
|
|
61
|
+
it('should track hits and misses', () => {
|
|
62
|
+
cache.set('key1', 'value1');
|
|
63
|
+
cache.get('key1'); // hit
|
|
64
|
+
cache.get('key1'); // hit
|
|
65
|
+
cache.get('missing'); // miss
|
|
66
|
+
const stats = cache.getStats();
|
|
67
|
+
expect(stats.hits).toBe(2);
|
|
68
|
+
expect(stats.misses).toBe(1);
|
|
69
|
+
expect(stats.hitRate).toBeCloseTo(0.667, 2);
|
|
70
|
+
});
|
|
71
|
+
it('should report size', () => {
|
|
72
|
+
cache.set('key1', 'value1');
|
|
73
|
+
cache.set('key2', 'value2');
|
|
74
|
+
const stats = cache.getStats();
|
|
75
|
+
expect(stats.size).toBe(2);
|
|
76
|
+
expect(stats.maxSize).toBe(5);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe('Cleanup', () => {
|
|
80
|
+
it('should cleanup expired entries', async () => {
|
|
81
|
+
const shortCache = new ValidationCache({ ttlMs: 50 });
|
|
82
|
+
shortCache.set('key1', 'value1');
|
|
83
|
+
shortCache.set('key2', 'value2');
|
|
84
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
85
|
+
const evicted = shortCache.cleanup();
|
|
86
|
+
expect(evicted).toBe(2);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
describe('RateLimiter', () => {
|
|
91
|
+
let limiter;
|
|
92
|
+
beforeEach(() => {
|
|
93
|
+
limiter = new RateLimiter();
|
|
94
|
+
});
|
|
95
|
+
afterEach(() => {
|
|
96
|
+
limiter.resetAll();
|
|
97
|
+
});
|
|
98
|
+
describe('Token Acquisition', () => {
|
|
99
|
+
it('should allow immediate requests within burst limit', async () => {
|
|
100
|
+
// npm has burstLimit of 20
|
|
101
|
+
for (let i = 0; i < 5; i++) {
|
|
102
|
+
await expect(limiter.acquire('npm')).resolves.toBeUndefined();
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
it('should track available tokens', () => {
|
|
106
|
+
const stats = limiter.getStats('npm');
|
|
107
|
+
expect(stats.availableTokens).toBeGreaterThan(0);
|
|
108
|
+
expect(stats.config.requestsPerSecond).toBe(10);
|
|
109
|
+
});
|
|
110
|
+
it('should queue requests when tokens exhausted', async () => {
|
|
111
|
+
// Exhaust all tokens
|
|
112
|
+
const burstLimit = API_RATE_LIMITS.audit.burstLimit; // 3 for audit
|
|
113
|
+
for (let i = 0; i < burstLimit; i++) {
|
|
114
|
+
await limiter.acquire('audit');
|
|
115
|
+
}
|
|
116
|
+
// Next request should be queued
|
|
117
|
+
const stats = limiter.getStats('audit');
|
|
118
|
+
expect(stats.availableTokens).toBe(0);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
describe('Rate Limit Configuration', () => {
|
|
122
|
+
it('should have default rate limits for npm', () => {
|
|
123
|
+
expect(API_RATE_LIMITS.npm).toEqual({
|
|
124
|
+
requestsPerSecond: 10,
|
|
125
|
+
burstLimit: 20,
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
it('should have default rate limits for bundlephobia', () => {
|
|
129
|
+
expect(API_RATE_LIMITS.bundlephobia).toEqual({
|
|
130
|
+
requestsPerSecond: 5,
|
|
131
|
+
burstLimit: 10,
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
it('should have default rate limits for audit', () => {
|
|
135
|
+
expect(API_RATE_LIMITS.audit).toEqual({
|
|
136
|
+
requestsPerSecond: 1,
|
|
137
|
+
burstLimit: 3,
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe('Reset', () => {
|
|
142
|
+
it('should reset a specific source', async () => {
|
|
143
|
+
await limiter.acquire('npm');
|
|
144
|
+
limiter.reset('npm');
|
|
145
|
+
const stats = limiter.getStats('npm');
|
|
146
|
+
expect(stats.queueLength).toBe(0);
|
|
147
|
+
});
|
|
148
|
+
it('should reset all sources', async () => {
|
|
149
|
+
await limiter.acquire('npm');
|
|
150
|
+
await limiter.acquire('audit');
|
|
151
|
+
limiter.resetAll();
|
|
152
|
+
// New stats should be fresh
|
|
153
|
+
const npmStats = limiter.getStats('npm');
|
|
154
|
+
expect(npmStats.queueLength).toBe(0);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
describe('Utility Functions', () => {
|
|
159
|
+
afterEach(() => {
|
|
160
|
+
rateLimiter.resetAll();
|
|
161
|
+
});
|
|
162
|
+
describe('withRateLimit', () => {
|
|
163
|
+
it('should execute function with rate limiting', async () => {
|
|
164
|
+
let called = false;
|
|
165
|
+
const result = await withRateLimit('npm', async () => {
|
|
166
|
+
called = true;
|
|
167
|
+
return 'result';
|
|
168
|
+
});
|
|
169
|
+
expect(called).toBe(true);
|
|
170
|
+
expect(result).toBe('result');
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
describe('rateLimited', () => {
|
|
174
|
+
it('should create rate-limited function', async () => {
|
|
175
|
+
const fn = rateLimited('npm', async (x) => x * 2);
|
|
176
|
+
const result = await fn(5);
|
|
177
|
+
expect(result).toBe(10);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
//# sourceMappingURL=validation-cache.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-cache.test.js","sourceRoot":"","sources":["../../../../src/core/agents/__tests__/validation-cache.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Blackboard - v12.
|
|
2
|
+
* Blackboard - v12.6.0
|
|
3
3
|
*
|
|
4
4
|
* Shared state coordination for multi-agent systems:
|
|
5
5
|
* - Resource claiming to prevent duplicate work
|
|
6
6
|
* - Shared key-value state
|
|
7
7
|
* - Lock mechanism to prevent races
|
|
8
8
|
* - File content caching
|
|
9
|
+
* - Persistent state across sessions
|
|
9
10
|
*/
|
|
10
11
|
import { type MessageBus } from './message-protocol.js';
|
|
11
12
|
/**
|
|
@@ -65,8 +66,8 @@ export interface BlackboardStats {
|
|
|
65
66
|
* - Lock mechanism for critical sections
|
|
66
67
|
*/
|
|
67
68
|
export declare class Blackboard {
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
claims: Map<string, ResourceClaim>;
|
|
70
|
+
state: Map<string, unknown>;
|
|
70
71
|
private cache;
|
|
71
72
|
private locks;
|
|
72
73
|
private messageBus;
|
|
@@ -75,7 +76,25 @@ export declare class Blackboard {
|
|
|
75
76
|
private cacheMisses;
|
|
76
77
|
private defaultLockTimeoutMs;
|
|
77
78
|
private defaultClaimExpiryMs;
|
|
79
|
+
private persistClaimChange;
|
|
80
|
+
private persistStateChange;
|
|
78
81
|
constructor(defaultLockTimeoutMs?: number, defaultClaimExpiryMs?: number);
|
|
82
|
+
/**
|
|
83
|
+
* Set persistence callbacks
|
|
84
|
+
*/
|
|
85
|
+
setPersistenceCallbacks(onClaimChange: (() => void) | null, onStateChange: (() => void) | null): void;
|
|
86
|
+
/**
|
|
87
|
+
* Load claims from persisted state
|
|
88
|
+
*/
|
|
89
|
+
loadClaims(claims: ResourceClaim[]): void;
|
|
90
|
+
/**
|
|
91
|
+
* Load shared state from persisted state
|
|
92
|
+
*/
|
|
93
|
+
loadState(state: Map<string, unknown>): void;
|
|
94
|
+
/**
|
|
95
|
+
* Get all claims as array (for persistence)
|
|
96
|
+
*/
|
|
97
|
+
getAllClaims(): ResourceClaim[];
|
|
79
98
|
/**
|
|
80
99
|
* Connect to a message bus for distributed coordination
|
|
81
100
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blackboard.d.ts","sourceRoot":"","sources":["../../../src/core/agents/blackboard.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"blackboard.d.ts","sourceRoot":"","sources":["../../../src/core/agents/blackboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Blackboard - v12.
|
|
2
|
+
* Blackboard - v12.6.0
|
|
3
3
|
*
|
|
4
4
|
* Shared state coordination for multi-agent systems:
|
|
5
5
|
* - Resource claiming to prevent duplicate work
|
|
6
6
|
* - Shared key-value state
|
|
7
7
|
* - Lock mechanism to prevent races
|
|
8
8
|
* - File content caching
|
|
9
|
+
* - Persistent state across sessions
|
|
9
10
|
*/
|
|
10
11
|
import { createBroadcast, createClaim, isBroadcast, isClaim, } from './message-protocol.js';
|
|
11
12
|
// =============================================================================
|
|
@@ -31,10 +32,44 @@ export class Blackboard {
|
|
|
31
32
|
cacheMisses = 0;
|
|
32
33
|
defaultLockTimeoutMs;
|
|
33
34
|
defaultClaimExpiryMs;
|
|
35
|
+
persistClaimChange = null;
|
|
36
|
+
persistStateChange = null;
|
|
34
37
|
constructor(defaultLockTimeoutMs = 5000, defaultClaimExpiryMs = 60000) {
|
|
35
38
|
this.defaultLockTimeoutMs = defaultLockTimeoutMs;
|
|
36
39
|
this.defaultClaimExpiryMs = defaultClaimExpiryMs;
|
|
37
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Set persistence callbacks
|
|
43
|
+
*/
|
|
44
|
+
setPersistenceCallbacks(onClaimChange, onStateChange) {
|
|
45
|
+
this.persistClaimChange = onClaimChange;
|
|
46
|
+
this.persistStateChange = onStateChange;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Load claims from persisted state
|
|
50
|
+
*/
|
|
51
|
+
loadClaims(claims) {
|
|
52
|
+
this.claims.clear();
|
|
53
|
+
for (const claim of claims) {
|
|
54
|
+
this.claims.set(claim.resource, claim);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Load shared state from persisted state
|
|
59
|
+
*/
|
|
60
|
+
loadState(state) {
|
|
61
|
+
this.state.clear();
|
|
62
|
+
for (const [key, value] of state) {
|
|
63
|
+
this.state.set(key, value);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get all claims as array (for persistence)
|
|
68
|
+
*/
|
|
69
|
+
getAllClaims() {
|
|
70
|
+
this.cleanupExpiredClaims();
|
|
71
|
+
return Array.from(this.claims.values());
|
|
72
|
+
}
|
|
38
73
|
/**
|
|
39
74
|
* Connect to a message bus for distributed coordination
|
|
40
75
|
*/
|
|
@@ -150,6 +185,10 @@ export class Blackboard {
|
|
|
150
185
|
metadata,
|
|
151
186
|
};
|
|
152
187
|
this.claims.set(resource, claim);
|
|
188
|
+
// Notify persistence
|
|
189
|
+
if (this.persistClaimChange) {
|
|
190
|
+
this.persistClaimChange();
|
|
191
|
+
}
|
|
153
192
|
// Broadcast claim to other agents
|
|
154
193
|
if (this.messageBus) {
|
|
155
194
|
const message = createClaim(agentId, 'claim', resource, metadata);
|
|
@@ -170,6 +209,10 @@ export class Blackboard {
|
|
|
170
209
|
return false; // Not owned by this agent
|
|
171
210
|
}
|
|
172
211
|
this.claims.delete(resource);
|
|
212
|
+
// Notify persistence
|
|
213
|
+
if (this.persistClaimChange) {
|
|
214
|
+
this.persistClaimChange();
|
|
215
|
+
}
|
|
173
216
|
// Broadcast release to other agents
|
|
174
217
|
if (this.messageBus) {
|
|
175
218
|
const message = createClaim(agentId, 'release', resource);
|
|
@@ -244,12 +287,19 @@ export class Blackboard {
|
|
|
244
287
|
*/
|
|
245
288
|
set(key, value) {
|
|
246
289
|
this.state.set(key, value);
|
|
290
|
+
if (this.persistStateChange) {
|
|
291
|
+
this.persistStateChange();
|
|
292
|
+
}
|
|
247
293
|
}
|
|
248
294
|
/**
|
|
249
295
|
* Delete a value from shared state
|
|
250
296
|
*/
|
|
251
297
|
delete(key) {
|
|
252
|
-
|
|
298
|
+
const result = this.state.delete(key);
|
|
299
|
+
if (result && this.persistStateChange) {
|
|
300
|
+
this.persistStateChange();
|
|
301
|
+
}
|
|
302
|
+
return result;
|
|
253
303
|
}
|
|
254
304
|
/**
|
|
255
305
|
* Check if key exists in shared state
|