cognitive-core 0.0.2 → 0.1.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/README.md +302 -116
- package/SKILL.md +193 -0
- package/dist/agents/index.d.ts +3 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +5 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/mock-provider.d.ts +23 -0
- package/dist/agents/mock-provider.d.ts.map +1 -0
- package/dist/agents/mock-provider.js +71 -0
- package/dist/agents/mock-provider.js.map +1 -0
- package/dist/agents/types.d.ts +98 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +44 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/atlas.d.ts +196 -0
- package/dist/atlas.d.ts.map +1 -0
- package/dist/atlas.js +373 -0
- package/dist/atlas.js.map +1 -0
- package/dist/bin/cognitive-core.d.ts +18 -0
- package/dist/bin/cognitive-core.d.ts.map +1 -0
- package/dist/bin/cognitive-core.js +419 -0
- package/dist/bin/cognitive-core.js.map +1 -0
- package/dist/embeddings/bm25.d.ts +104 -0
- package/dist/embeddings/bm25.d.ts.map +1 -0
- package/dist/embeddings/bm25.js +264 -0
- package/dist/embeddings/bm25.js.map +1 -0
- package/dist/embeddings/index.d.ts +12 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +16 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/embeddings/manager.d.ts +112 -0
- package/dist/embeddings/manager.d.ts.map +1 -0
- package/dist/embeddings/manager.js +215 -0
- package/dist/embeddings/manager.js.map +1 -0
- package/dist/embeddings/provider.d.ts +101 -0
- package/dist/embeddings/provider.d.ts.map +1 -0
- package/dist/embeddings/provider.js +232 -0
- package/dist/embeddings/provider.js.map +1 -0
- package/dist/embeddings/vector-store.d.ts +101 -0
- package/dist/embeddings/vector-store.d.ts.map +1 -0
- package/dist/embeddings/vector-store.js +256 -0
- package/dist/embeddings/vector-store.js.map +1 -0
- package/dist/factory.d.ts +193 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +109 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +30 -453
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -509
- package/dist/index.js.map +1 -0
- package/dist/learning/analyzer.d.ts +110 -0
- package/dist/learning/analyzer.d.ts.map +1 -0
- package/dist/learning/analyzer.js +213 -0
- package/dist/learning/analyzer.js.map +1 -0
- package/dist/learning/effectiveness.d.ts +158 -0
- package/dist/learning/effectiveness.d.ts.map +1 -0
- package/dist/learning/effectiveness.js +251 -0
- package/dist/learning/effectiveness.js.map +1 -0
- package/dist/learning/index.d.ts +8 -0
- package/dist/learning/index.d.ts.map +1 -0
- package/dist/learning/index.js +11 -0
- package/dist/learning/index.js.map +1 -0
- package/dist/learning/llm-extractor.d.ts +88 -0
- package/dist/learning/llm-extractor.d.ts.map +1 -0
- package/dist/learning/llm-extractor.js +372 -0
- package/dist/learning/llm-extractor.js.map +1 -0
- package/dist/learning/meta-learner.d.ts +80 -0
- package/dist/learning/meta-learner.d.ts.map +1 -0
- package/dist/learning/meta-learner.js +355 -0
- package/dist/learning/meta-learner.js.map +1 -0
- package/dist/learning/pipeline.d.ts +65 -0
- package/dist/learning/pipeline.d.ts.map +1 -0
- package/dist/learning/pipeline.js +170 -0
- package/dist/learning/pipeline.js.map +1 -0
- package/dist/learning/playbook-extractor.d.ts +113 -0
- package/dist/learning/playbook-extractor.d.ts.map +1 -0
- package/dist/learning/playbook-extractor.js +523 -0
- package/dist/learning/playbook-extractor.js.map +1 -0
- package/dist/learning/usage-inference.d.ts +82 -0
- package/dist/learning/usage-inference.d.ts.map +1 -0
- package/dist/learning/usage-inference.js +261 -0
- package/dist/learning/usage-inference.js.map +1 -0
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +6 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/playbook-server.d.ts +120 -0
- package/dist/mcp/playbook-server.d.ts.map +1 -0
- package/dist/mcp/playbook-server.js +427 -0
- package/dist/mcp/playbook-server.js.map +1 -0
- package/dist/memory/curated-loader.d.ts +62 -0
- package/dist/memory/curated-loader.d.ts.map +1 -0
- package/dist/memory/curated-loader.js +106 -0
- package/dist/memory/curated-loader.js.map +1 -0
- package/dist/memory/experience.d.ts +122 -0
- package/dist/memory/experience.d.ts.map +1 -0
- package/dist/memory/experience.js +392 -0
- package/dist/memory/experience.js.map +1 -0
- package/dist/memory/index.d.ts +6 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/meta.d.ts +90 -0
- package/dist/memory/meta.d.ts.map +1 -0
- package/dist/memory/meta.js +362 -0
- package/dist/memory/meta.js.map +1 -0
- package/dist/memory/playbook.d.ts +133 -0
- package/dist/memory/playbook.d.ts.map +1 -0
- package/dist/memory/playbook.js +357 -0
- package/dist/memory/playbook.js.map +1 -0
- package/dist/memory/system.d.ts +167 -0
- package/dist/memory/system.d.ts.map +1 -0
- package/dist/memory/system.js +383 -0
- package/dist/memory/system.js.map +1 -0
- package/dist/runtime/backends/acp.d.ts +67 -0
- package/dist/runtime/backends/acp.d.ts.map +1 -0
- package/dist/runtime/backends/acp.js +290 -0
- package/dist/runtime/backends/acp.js.map +1 -0
- package/dist/runtime/backends/index.d.ts +5 -0
- package/dist/runtime/backends/index.d.ts.map +1 -0
- package/dist/runtime/backends/index.js +6 -0
- package/dist/runtime/backends/index.js.map +1 -0
- package/dist/runtime/backends/mock.d.ts +67 -0
- package/dist/runtime/backends/mock.d.ts.map +1 -0
- package/dist/runtime/backends/mock.js +153 -0
- package/dist/runtime/backends/mock.js.map +1 -0
- package/dist/runtime/backends/subprocess.d.ts +56 -0
- package/dist/runtime/backends/subprocess.d.ts.map +1 -0
- package/dist/runtime/backends/subprocess.js +260 -0
- package/dist/runtime/backends/subprocess.js.map +1 -0
- package/dist/runtime/flows/learning.d.ts +73 -0
- package/dist/runtime/flows/learning.d.ts.map +1 -0
- package/dist/runtime/flows/learning.js +116 -0
- package/dist/runtime/flows/learning.js.map +1 -0
- package/dist/runtime/flows/validation.d.ts +122 -0
- package/dist/runtime/flows/validation.d.ts.map +1 -0
- package/dist/runtime/flows/validation.js +223 -0
- package/dist/runtime/flows/validation.js.map +1 -0
- package/dist/runtime/index.d.ts +6 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/manager.d.ts +116 -0
- package/dist/runtime/manager.d.ts.map +1 -0
- package/dist/runtime/manager.js +416 -0
- package/dist/runtime/manager.js.map +1 -0
- package/dist/runtime/types.d.ts +138 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/search/evaluator.d.ts +102 -0
- package/dist/search/evaluator.d.ts.map +1 -0
- package/dist/search/evaluator.js +352 -0
- package/dist/search/evaluator.js.map +1 -0
- package/dist/search/index.d.ts +7 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +11 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/refinement-loop.d.ts +73 -0
- package/dist/search/refinement-loop.d.ts.map +1 -0
- package/dist/search/refinement-loop.js +245 -0
- package/dist/search/refinement-loop.js.map +1 -0
- package/dist/search/refinement-types.d.ts +154 -0
- package/dist/search/refinement-types.d.ts.map +1 -0
- package/dist/search/refinement-types.js +99 -0
- package/dist/search/refinement-types.js.map +1 -0
- package/dist/search/router.d.ts +61 -0
- package/dist/search/router.d.ts.map +1 -0
- package/dist/search/router.js +197 -0
- package/dist/search/router.js.map +1 -0
- package/dist/search/solver.d.ts +75 -0
- package/dist/search/solver.d.ts.map +1 -0
- package/dist/search/solver.js +216 -0
- package/dist/search/solver.js.map +1 -0
- package/dist/search/verification-runner.d.ts +125 -0
- package/dist/search/verification-runner.d.ts.map +1 -0
- package/dist/search/verification-runner.js +440 -0
- package/dist/search/verification-runner.js.map +1 -0
- package/dist/surfacing/index.d.ts +2 -0
- package/dist/surfacing/index.d.ts.map +1 -0
- package/dist/surfacing/index.js +2 -0
- package/dist/surfacing/index.js.map +1 -0
- package/dist/surfacing/skill-library.d.ts +158 -0
- package/dist/surfacing/skill-library.d.ts.map +1 -0
- package/dist/surfacing/skill-library.js +429 -0
- package/dist/surfacing/skill-library.js.map +1 -0
- package/dist/types/config.d.ts +1113 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +274 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +14 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/memory.d.ts +339 -0
- package/dist/types/memory.d.ts.map +1 -0
- package/dist/types/memory.js +207 -0
- package/dist/types/memory.js.map +1 -0
- package/dist/types/meta.d.ts +146 -0
- package/dist/types/meta.d.ts.map +1 -0
- package/dist/types/meta.js +51 -0
- package/dist/types/meta.js.map +1 -0
- package/dist/types/outcome.d.ts +42 -0
- package/dist/types/outcome.d.ts.map +1 -0
- package/dist/types/outcome.js +50 -0
- package/dist/types/outcome.js.map +1 -0
- package/dist/types/playbook.d.ts +119 -0
- package/dist/types/playbook.d.ts.map +1 -0
- package/dist/types/playbook.js +71 -0
- package/dist/types/playbook.js.map +1 -0
- package/dist/types/step.d.ts +44 -0
- package/dist/types/step.d.ts.map +1 -0
- package/dist/types/step.js +32 -0
- package/dist/types/step.js.map +1 -0
- package/dist/types/task.d.ts +91 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +39 -0
- package/dist/types/task.js.map +1 -0
- package/dist/types/trajectory.d.ts +221 -0
- package/dist/types/trajectory.d.ts.map +1 -0
- package/dist/types/trajectory.js +60 -0
- package/dist/types/trajectory.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/similarity.d.ts +31 -0
- package/dist/utils/similarity.d.ts.map +1 -0
- package/dist/utils/similarity.js +107 -0
- package/dist/utils/similarity.js.map +1 -0
- package/dist/utils/storage.d.ts +106 -0
- package/dist/utils/storage.d.ts.map +1 -0
- package/dist/utils/storage.js +203 -0
- package/dist/utils/storage.js.map +1 -0
- package/dist/utils/validation.d.ts +129 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +171 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +50 -34
- package/scripts/migrate-to-playbooks.ts +307 -0
- package/src/agents/index.ts +14 -0
- package/src/agents/mock-provider.ts +93 -0
- package/src/agents/types.ts +137 -0
- package/src/atlas.ts +560 -0
- package/src/bin/cognitive-core.ts +470 -0
- package/src/embeddings/bm25.ts +337 -0
- package/src/embeddings/index.ts +39 -0
- package/src/embeddings/manager.ts +288 -0
- package/src/embeddings/provider.ts +311 -0
- package/src/embeddings/vector-store.ts +353 -0
- package/src/factory.ts +263 -0
- package/src/index.ts +246 -0
- package/src/learning/analyzer.ts +335 -0
- package/src/learning/effectiveness.ts +428 -0
- package/src/learning/index.ts +58 -0
- package/src/learning/llm-extractor.ts +542 -0
- package/src/learning/meta-learner.ts +516 -0
- package/src/learning/pipeline.ts +244 -0
- package/src/learning/playbook-extractor.ts +702 -0
- package/src/learning/usage-inference.ts +372 -0
- package/src/mcp/index.ts +12 -0
- package/src/mcp/playbook-server.ts +565 -0
- package/src/memory/curated-loader.ts +160 -0
- package/src/memory/experience.ts +515 -0
- package/src/memory/index.ts +27 -0
- package/src/memory/meta.ts +506 -0
- package/src/memory/playbook.ts +493 -0
- package/src/memory/system.ts +551 -0
- package/src/runtime/backends/acp.ts +378 -0
- package/src/runtime/backends/index.ts +24 -0
- package/src/runtime/backends/mock.ts +218 -0
- package/src/runtime/backends/subprocess.ts +356 -0
- package/src/runtime/flows/learning.ts +183 -0
- package/src/runtime/flows/validation.ts +381 -0
- package/src/runtime/index.ts +53 -0
- package/src/runtime/manager.ts +541 -0
- package/src/runtime/types.ts +157 -0
- package/src/search/evaluator.ts +474 -0
- package/src/search/index.ts +59 -0
- package/src/search/refinement-loop.ts +363 -0
- package/src/search/refinement-types.ts +159 -0
- package/src/search/router.ts +261 -0
- package/src/search/solver.ts +303 -0
- package/src/search/verification-runner.ts +570 -0
- package/src/surfacing/index.ts +6 -0
- package/src/surfacing/skill-library.ts +594 -0
- package/src/types/config.ts +333 -0
- package/src/types/index.ts +130 -0
- package/src/types/memory.ts +270 -0
- package/src/types/meta.ts +218 -0
- package/src/types/outcome.ts +66 -0
- package/src/types/playbook.ts +196 -0
- package/src/types/step.ts +40 -0
- package/src/types/task.ts +52 -0
- package/src/types/trajectory.ts +80 -0
- package/src/utils/index.ts +38 -0
- package/src/utils/similarity.ts +139 -0
- package/src/utils/storage.ts +249 -0
- package/src/utils/validation.ts +286 -0
- package/tests/embeddings/bm25.test.ts +130 -0
- package/tests/embeddings/manager.test.ts +205 -0
- package/tests/integration/atlas.test.ts +266 -0
- package/tests/integration/e2e.test.ts +929 -0
- package/tests/learning/analyzer.test.ts +426 -0
- package/tests/learning/effectiveness.test.ts +542 -0
- package/tests/learning/pipeline.test.ts +176 -0
- package/tests/learning/playbook-extractor-provenance.test.ts +114 -0
- package/tests/learning/usage-inference.test.ts +254 -0
- package/tests/mcp/playbook-server.test.ts +252 -0
- package/tests/memory/experience.test.ts +198 -0
- package/tests/memory/playbook.test.ts +338 -0
- package/tests/memory/provenance.test.ts +639 -0
- package/tests/memory/system.test.ts +325 -0
- package/tests/runtime/agent-manager.test.ts +512 -0
- package/tests/runtime/mock-backend.test.ts +248 -0
- package/tests/search/refinement-loop.test.ts +468 -0
- package/tests/search/refinement.test.ts +267 -0
- package/tests/search/router.test.ts +427 -0
- package/tests/surfacing/skill-library.test.ts +292 -0
- package/tests/types/outcome.test.ts +147 -0
- package/tests/types/step.test.ts +133 -0
- package/tests/types/task.test.ts +158 -0
- package/tests/types/trajectory.test.ts +253 -0
- package/tests/utils/similarity.test.ts +188 -0
- package/tests/utils/validation.test.ts +252 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +22 -0
- package/dist/index.d.mts +0 -466
- package/dist/index.mjs +0 -478
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
createEvaluationResult,
|
|
4
|
+
scoreToQuality,
|
|
5
|
+
isQualityAcceptable,
|
|
6
|
+
type EvaluationResult,
|
|
7
|
+
type QualityLevel,
|
|
8
|
+
} from '../../src/search/refinement-types.js';
|
|
9
|
+
import {
|
|
10
|
+
SolutionEvaluator,
|
|
11
|
+
createSolutionEvaluator,
|
|
12
|
+
type VerificationResult,
|
|
13
|
+
} from '../../src/search/evaluator.js';
|
|
14
|
+
import type { Trajectory } from '../../src/types/trajectory.js';
|
|
15
|
+
import type { Task } from '../../src/types/task.js';
|
|
16
|
+
|
|
17
|
+
describe('Refinement Types', () => {
|
|
18
|
+
describe('scoreToQuality', () => {
|
|
19
|
+
it('should return excellent for scores >= 0.85', () => {
|
|
20
|
+
expect(scoreToQuality(0.85)).toBe('excellent');
|
|
21
|
+
expect(scoreToQuality(0.9)).toBe('excellent');
|
|
22
|
+
expect(scoreToQuality(1.0)).toBe('excellent');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return good for scores >= 0.7 and < 0.85', () => {
|
|
26
|
+
expect(scoreToQuality(0.7)).toBe('good');
|
|
27
|
+
expect(scoreToQuality(0.8)).toBe('good');
|
|
28
|
+
expect(scoreToQuality(0.84)).toBe('good');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should return needs_work for scores >= 0.4 and < 0.7', () => {
|
|
32
|
+
expect(scoreToQuality(0.4)).toBe('needs_work');
|
|
33
|
+
expect(scoreToQuality(0.5)).toBe('needs_work');
|
|
34
|
+
expect(scoreToQuality(0.69)).toBe('needs_work');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should return poor for scores < 0.4', () => {
|
|
38
|
+
expect(scoreToQuality(0)).toBe('poor');
|
|
39
|
+
expect(scoreToQuality(0.2)).toBe('poor');
|
|
40
|
+
expect(scoreToQuality(0.39)).toBe('poor');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('isQualityAcceptable', () => {
|
|
45
|
+
it('should accept quality >= minAcceptable', () => {
|
|
46
|
+
expect(isQualityAcceptable('excellent', 'good')).toBe(true);
|
|
47
|
+
expect(isQualityAcceptable('good', 'good')).toBe(true);
|
|
48
|
+
expect(isQualityAcceptable('excellent', 'excellent')).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should reject quality < minAcceptable', () => {
|
|
52
|
+
expect(isQualityAcceptable('needs_work', 'good')).toBe(false);
|
|
53
|
+
expect(isQualityAcceptable('poor', 'good')).toBe(false);
|
|
54
|
+
expect(isQualityAcceptable('good', 'excellent')).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should use good as default minAcceptable', () => {
|
|
58
|
+
expect(isQualityAcceptable('good')).toBe(true);
|
|
59
|
+
expect(isQualityAcceptable('excellent')).toBe(true);
|
|
60
|
+
expect(isQualityAcceptable('needs_work')).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('createEvaluationResult', () => {
|
|
65
|
+
it('should create a valid evaluation result', () => {
|
|
66
|
+
const result = createEvaluationResult({
|
|
67
|
+
quality: 'good',
|
|
68
|
+
score: 0.75,
|
|
69
|
+
acceptable: true,
|
|
70
|
+
issues: [],
|
|
71
|
+
method: 'verification',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(result.quality).toBe('good');
|
|
75
|
+
expect(result.score).toBe(0.75);
|
|
76
|
+
expect(result.acceptable).toBe(true);
|
|
77
|
+
expect(result.issues).toEqual([]);
|
|
78
|
+
expect(result.method).toBe('verification');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should validate score bounds', () => {
|
|
82
|
+
expect(() => createEvaluationResult({
|
|
83
|
+
quality: 'good',
|
|
84
|
+
score: 1.5,
|
|
85
|
+
acceptable: true,
|
|
86
|
+
method: 'verification',
|
|
87
|
+
})).toThrow();
|
|
88
|
+
|
|
89
|
+
expect(() => createEvaluationResult({
|
|
90
|
+
quality: 'good',
|
|
91
|
+
score: -0.1,
|
|
92
|
+
acceptable: true,
|
|
93
|
+
method: 'verification',
|
|
94
|
+
})).toThrow();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should include issues when provided', () => {
|
|
98
|
+
const result = createEvaluationResult({
|
|
99
|
+
quality: 'needs_work',
|
|
100
|
+
score: 0.5,
|
|
101
|
+
acceptable: false,
|
|
102
|
+
issues: [
|
|
103
|
+
{ type: 'incomplete', description: 'Missing tests', severity: 'major' },
|
|
104
|
+
],
|
|
105
|
+
method: 'agent',
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
expect(result.issues.length).toBe(1);
|
|
109
|
+
expect(result.issues[0].type).toBe('incomplete');
|
|
110
|
+
expect(result.issues[0].description).toBe('Missing tests');
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('SolutionEvaluator', () => {
|
|
116
|
+
const createMockTrajectory = (success: boolean): Trajectory => ({
|
|
117
|
+
id: 'test-trajectory',
|
|
118
|
+
task: {
|
|
119
|
+
id: 'test-task',
|
|
120
|
+
description: 'Test task',
|
|
121
|
+
domain: 'test',
|
|
122
|
+
context: {},
|
|
123
|
+
metadata: {},
|
|
124
|
+
createdAt: new Date(),
|
|
125
|
+
},
|
|
126
|
+
steps: [
|
|
127
|
+
{
|
|
128
|
+
action: 'test action',
|
|
129
|
+
observation: 'test observation',
|
|
130
|
+
metadata: {},
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
outcome: {
|
|
134
|
+
success,
|
|
135
|
+
partialScore: success ? 1.0 : 0.0,
|
|
136
|
+
errorInfo: success ? undefined : 'Test error',
|
|
137
|
+
verificationDetails: {},
|
|
138
|
+
solution: success ? 'Test solution' : undefined,
|
|
139
|
+
},
|
|
140
|
+
agentId: 'test-agent',
|
|
141
|
+
timestamp: new Date(),
|
|
142
|
+
llmCalls: 1,
|
|
143
|
+
totalTokens: 100,
|
|
144
|
+
wallTimeSeconds: 1,
|
|
145
|
+
metadata: {},
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const createMockTask = (): Task => ({
|
|
149
|
+
id: 'test-task',
|
|
150
|
+
description: 'Test task description',
|
|
151
|
+
domain: 'test',
|
|
152
|
+
context: {},
|
|
153
|
+
metadata: {},
|
|
154
|
+
createdAt: new Date(),
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe('heuristic evaluation', () => {
|
|
158
|
+
let evaluator: SolutionEvaluator;
|
|
159
|
+
|
|
160
|
+
beforeEach(() => {
|
|
161
|
+
evaluator = createSolutionEvaluator(null);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should evaluate successful trajectory positively', async () => {
|
|
165
|
+
const trajectory = createMockTrajectory(true);
|
|
166
|
+
const task = createMockTask();
|
|
167
|
+
|
|
168
|
+
const result = await evaluator.evaluate(trajectory, task);
|
|
169
|
+
|
|
170
|
+
expect(result.score).toBeGreaterThan(0.5);
|
|
171
|
+
expect(result.method).toBe('heuristic');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should evaluate failed trajectory negatively', async () => {
|
|
175
|
+
const trajectory = createMockTrajectory(false);
|
|
176
|
+
const task = createMockTask();
|
|
177
|
+
|
|
178
|
+
const result = await evaluator.evaluate(trajectory, task);
|
|
179
|
+
|
|
180
|
+
expect(result.score).toBeLessThanOrEqual(0.5);
|
|
181
|
+
expect(result.acceptable).toBe(false);
|
|
182
|
+
expect(result.issues.length).toBeGreaterThan(0);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should penalize trajectories with no steps', async () => {
|
|
186
|
+
const trajectory = createMockTrajectory(false);
|
|
187
|
+
trajectory.steps = [];
|
|
188
|
+
const task = createMockTask();
|
|
189
|
+
|
|
190
|
+
const result = await evaluator.evaluate(trajectory, task);
|
|
191
|
+
|
|
192
|
+
expect(result.score).toBeLessThan(0.5);
|
|
193
|
+
const incompleteIssue = result.issues.find(i => i.type === 'incomplete');
|
|
194
|
+
expect(incompleteIssue).toBeDefined();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('should penalize long trajectories', async () => {
|
|
198
|
+
const trajectory = createMockTrajectory(true);
|
|
199
|
+
trajectory.steps = Array(25).fill({
|
|
200
|
+
action: 'action',
|
|
201
|
+
observation: 'observation',
|
|
202
|
+
metadata: {},
|
|
203
|
+
});
|
|
204
|
+
const task = createMockTask();
|
|
205
|
+
|
|
206
|
+
const result = await evaluator.evaluate(trajectory, task);
|
|
207
|
+
|
|
208
|
+
const inefficientIssue = result.issues.find(i => i.type === 'inefficient');
|
|
209
|
+
expect(inefficientIssue).toBeDefined();
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe('verification', () => {
|
|
214
|
+
it('should use registered verifier for domain', async () => {
|
|
215
|
+
const evaluator = createSolutionEvaluator(null);
|
|
216
|
+
|
|
217
|
+
const mockVerifier = vi.fn().mockResolvedValue({
|
|
218
|
+
passed: true,
|
|
219
|
+
confidence: 0.9,
|
|
220
|
+
} as VerificationResult);
|
|
221
|
+
|
|
222
|
+
evaluator.registerVerifier('test', mockVerifier);
|
|
223
|
+
|
|
224
|
+
const trajectory = createMockTrajectory(true);
|
|
225
|
+
const task = createMockTask();
|
|
226
|
+
|
|
227
|
+
const result = await evaluator.evaluate(trajectory, task);
|
|
228
|
+
|
|
229
|
+
expect(mockVerifier).toHaveBeenCalled();
|
|
230
|
+
expect(result.method).toBe('verification');
|
|
231
|
+
expect(result.acceptable).toBe(true);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('should fall back to heuristic if verifier fails', async () => {
|
|
235
|
+
const evaluator = createSolutionEvaluator(null);
|
|
236
|
+
|
|
237
|
+
const mockVerifier = vi.fn().mockRejectedValue(new Error('Verification error'));
|
|
238
|
+
evaluator.registerVerifier('test', mockVerifier);
|
|
239
|
+
|
|
240
|
+
const trajectory = createMockTrajectory(true);
|
|
241
|
+
const task = createMockTask();
|
|
242
|
+
|
|
243
|
+
const result = await evaluator.evaluate(trajectory, task);
|
|
244
|
+
|
|
245
|
+
expect(result.method).toBe('heuristic');
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('should not use verifier for unknown domain', async () => {
|
|
249
|
+
const evaluator = createSolutionEvaluator(null);
|
|
250
|
+
|
|
251
|
+
const mockVerifier = vi.fn().mockResolvedValue({
|
|
252
|
+
passed: true,
|
|
253
|
+
confidence: 0.9,
|
|
254
|
+
} as VerificationResult);
|
|
255
|
+
|
|
256
|
+
evaluator.registerVerifier('other', mockVerifier);
|
|
257
|
+
|
|
258
|
+
const trajectory = createMockTrajectory(true);
|
|
259
|
+
const task = createMockTask();
|
|
260
|
+
|
|
261
|
+
const result = await evaluator.evaluate(trajectory, task);
|
|
262
|
+
|
|
263
|
+
expect(mockVerifier).not.toHaveBeenCalled();
|
|
264
|
+
expect(result.method).toBe('heuristic');
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
});
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import { TaskRouter, createRouter, type RoutingDecision } from '../../src/search/router.js';
|
|
3
|
+
import { createMemorySystem } from '../../src/memory/system.js';
|
|
4
|
+
import { createTask } from '../../src/types/task.js';
|
|
5
|
+
import type { MemorySystem } from '../../src/memory/system.js';
|
|
6
|
+
import type { MetaLearner } from '../../src/learning/meta-learner.js';
|
|
7
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { tmpdir } from 'node:os';
|
|
10
|
+
|
|
11
|
+
describe('TaskRouter', () => {
|
|
12
|
+
let tempDir: string;
|
|
13
|
+
let memory: MemorySystem;
|
|
14
|
+
let router: TaskRouter;
|
|
15
|
+
|
|
16
|
+
beforeEach(async () => {
|
|
17
|
+
tempDir = await mkdtemp(join(tmpdir(), 'router-test-'));
|
|
18
|
+
memory = createMemorySystem(tempDir);
|
|
19
|
+
await memory.init();
|
|
20
|
+
router = createRouter(memory);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
afterEach(async () => {
|
|
24
|
+
await memory.close();
|
|
25
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('basic routing', () => {
|
|
29
|
+
it('should return fallback strategy when no memory exists', async () => {
|
|
30
|
+
const task = createTask({
|
|
31
|
+
domain: 'test',
|
|
32
|
+
description: 'A completely new task with no similar experiences',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const decision = await router.route(task);
|
|
36
|
+
|
|
37
|
+
expect(decision.strategy).toBe('fallback');
|
|
38
|
+
expect(decision.confidence).toBeLessThan(0.5);
|
|
39
|
+
expect(decision.memoryContext).toBeDefined();
|
|
40
|
+
expect(decision.reasoning).toContain('No relevant memory');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should return direct strategy when high-confidence playbook exists', async () => {
|
|
44
|
+
// Add a high-confidence playbook with very matching situations
|
|
45
|
+
await memory.playbooks.add({
|
|
46
|
+
id: 'playbook-1',
|
|
47
|
+
name: 'Fix TypeScript errors',
|
|
48
|
+
applicability: {
|
|
49
|
+
situations: ['Fix TypeScript type error in user module', 'TypeScript compilation error', 'Type mismatch in code'],
|
|
50
|
+
triggers: ['tsc error', 'type error', 'TypeScript type error'],
|
|
51
|
+
antiPatterns: [],
|
|
52
|
+
domains: ['typescript', 'code'],
|
|
53
|
+
},
|
|
54
|
+
guidance: {
|
|
55
|
+
strategy: 'Read error message, identify type mismatch, fix types',
|
|
56
|
+
tactics: ['Check variable types', 'Add type annotations'],
|
|
57
|
+
steps: ['Read error', 'Find source', 'Fix type'],
|
|
58
|
+
},
|
|
59
|
+
verification: {
|
|
60
|
+
successIndicators: ['No compilation errors'],
|
|
61
|
+
failureIndicators: ['Still has errors'],
|
|
62
|
+
},
|
|
63
|
+
evolution: {
|
|
64
|
+
version: '1.0.0',
|
|
65
|
+
createdFrom: [],
|
|
66
|
+
failures: [],
|
|
67
|
+
refinements: [],
|
|
68
|
+
successCount: 10,
|
|
69
|
+
failureCount: 1,
|
|
70
|
+
},
|
|
71
|
+
confidence: 0.9,
|
|
72
|
+
complexity: 'simple',
|
|
73
|
+
estimatedEffort: 1,
|
|
74
|
+
createdAt: new Date(),
|
|
75
|
+
updatedAt: new Date(),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const task = createTask({
|
|
79
|
+
domain: 'typescript',
|
|
80
|
+
description: 'Fix TypeScript type error in user module',
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const decision = await router.route(task);
|
|
84
|
+
|
|
85
|
+
// With matching playbook, should get direct strategy or at least find playbooks
|
|
86
|
+
expect(decision.memoryContext).toBeDefined();
|
|
87
|
+
// Strategy depends on similarity matching - may be direct or explore
|
|
88
|
+
expect(['direct', 'explore', 'fallback']).toContain(decision.strategy);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should return adapt strategy when similar successful experience exists', async () => {
|
|
92
|
+
// Add a successful experience
|
|
93
|
+
await memory.experiences.add({
|
|
94
|
+
id: 'exp-1',
|
|
95
|
+
taskInput: 'Fix authentication bug in login flow',
|
|
96
|
+
solutionOutput: 'Added proper token validation and error handling',
|
|
97
|
+
feedback: 'Successfully fixed the auth bug',
|
|
98
|
+
success: true,
|
|
99
|
+
domain: 'auth',
|
|
100
|
+
trajectoryId: 'traj-1',
|
|
101
|
+
usageCount: 0,
|
|
102
|
+
createdAt: new Date(),
|
|
103
|
+
metadata: {},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const task = createTask({
|
|
107
|
+
domain: 'auth',
|
|
108
|
+
description: 'Fix authentication bug in login flow for mobile',
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const decision = await router.route(task);
|
|
112
|
+
|
|
113
|
+
// Should find the similar experience
|
|
114
|
+
expect(decision.memoryContext.experiences.length).toBeGreaterThan(0);
|
|
115
|
+
// Strategy depends on similarity score
|
|
116
|
+
expect(['adapt', 'explore', 'direct']).toContain(decision.strategy);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should return explore strategy when low similarity experiences exist', async () => {
|
|
120
|
+
// Add an experience with somewhat related content
|
|
121
|
+
await memory.experiences.add({
|
|
122
|
+
id: 'exp-partial',
|
|
123
|
+
taskInput: 'Implement user profile page',
|
|
124
|
+
solutionOutput: 'Created React component with user data',
|
|
125
|
+
feedback: 'Profile page works',
|
|
126
|
+
success: true,
|
|
127
|
+
domain: 'frontend',
|
|
128
|
+
trajectoryId: 'traj-partial',
|
|
129
|
+
usageCount: 0,
|
|
130
|
+
createdAt: new Date(),
|
|
131
|
+
metadata: {},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const task = createTask({
|
|
135
|
+
domain: 'frontend',
|
|
136
|
+
description: 'Add settings page with dark mode toggle',
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const decision = await router.route(task);
|
|
140
|
+
|
|
141
|
+
expect(decision.memoryContext).toBeDefined();
|
|
142
|
+
// With partial similarity, should get explore or fallback
|
|
143
|
+
expect(['explore', 'fallback', 'direct']).toContain(decision.strategy);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe('domain routing', () => {
|
|
148
|
+
it('should filter by domain when useDomainRouting is enabled', async () => {
|
|
149
|
+
// Add experiences in different domains
|
|
150
|
+
await memory.experiences.add({
|
|
151
|
+
id: 'exp-frontend',
|
|
152
|
+
taskInput: 'Build React component',
|
|
153
|
+
solutionOutput: 'Created component',
|
|
154
|
+
feedback: 'Works',
|
|
155
|
+
success: true,
|
|
156
|
+
domain: 'frontend',
|
|
157
|
+
trajectoryId: 'traj-fe',
|
|
158
|
+
usageCount: 0,
|
|
159
|
+
createdAt: new Date(),
|
|
160
|
+
metadata: {},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
await memory.experiences.add({
|
|
164
|
+
id: 'exp-backend',
|
|
165
|
+
taskInput: 'Build API endpoint',
|
|
166
|
+
solutionOutput: 'Created endpoint',
|
|
167
|
+
feedback: 'Works',
|
|
168
|
+
success: true,
|
|
169
|
+
domain: 'backend',
|
|
170
|
+
trajectoryId: 'traj-be',
|
|
171
|
+
usageCount: 0,
|
|
172
|
+
createdAt: new Date(),
|
|
173
|
+
metadata: {},
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const frontendRouter = createRouter(memory, { useDomainRouting: true });
|
|
177
|
+
const task = createTask({
|
|
178
|
+
domain: 'frontend',
|
|
179
|
+
description: 'Build React component for dashboard',
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const decision = await frontendRouter.route(task);
|
|
183
|
+
|
|
184
|
+
// Should prioritize frontend experiences
|
|
185
|
+
expect(decision.memoryContext).toBeDefined();
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('configuration', () => {
|
|
190
|
+
it('should respect similarityThreshold config', async () => {
|
|
191
|
+
const strictRouter = createRouter(memory, { similarityThreshold: 0.95 });
|
|
192
|
+
|
|
193
|
+
await memory.experiences.add({
|
|
194
|
+
id: 'exp-strict',
|
|
195
|
+
taskInput: 'Test task',
|
|
196
|
+
solutionOutput: 'Test solution',
|
|
197
|
+
feedback: 'Good',
|
|
198
|
+
success: true,
|
|
199
|
+
domain: 'test',
|
|
200
|
+
trajectoryId: 'traj-strict',
|
|
201
|
+
usageCount: 0,
|
|
202
|
+
createdAt: new Date(),
|
|
203
|
+
metadata: {},
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const task = createTask({
|
|
207
|
+
domain: 'test',
|
|
208
|
+
description: 'Slightly different test task',
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const decision = await strictRouter.route(task);
|
|
212
|
+
|
|
213
|
+
// With strict threshold, should fall back more often
|
|
214
|
+
expect(decision.confidence).toBeDefined();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should use defaultStrategy from config', async () => {
|
|
218
|
+
const exploreRouter = createRouter(memory, { defaultStrategy: 'explore' });
|
|
219
|
+
|
|
220
|
+
const task = createTask({
|
|
221
|
+
domain: 'unknown',
|
|
222
|
+
description: 'Completely novel task',
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const decision = await exploreRouter.route(task);
|
|
226
|
+
|
|
227
|
+
// When no memory, should use default strategy reasoning
|
|
228
|
+
expect(decision).toBeDefined();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('should update config dynamically', () => {
|
|
232
|
+
router.updateConfig({ similarityThreshold: 0.5 });
|
|
233
|
+
// Config is updated internally
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
describe('routing decision structure', () => {
|
|
238
|
+
it('should include all required fields in routing decision', async () => {
|
|
239
|
+
const task = createTask({
|
|
240
|
+
domain: 'test',
|
|
241
|
+
description: 'Test task',
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
const decision = await router.route(task);
|
|
245
|
+
|
|
246
|
+
expect(decision.strategy).toBeDefined();
|
|
247
|
+
expect(['direct', 'adapt', 'explore', 'fallback']).toContain(decision.strategy);
|
|
248
|
+
expect(decision.confidence).toBeGreaterThanOrEqual(0);
|
|
249
|
+
expect(decision.confidence).toBeLessThanOrEqual(1);
|
|
250
|
+
expect(decision.memoryContext).toBeDefined();
|
|
251
|
+
expect(decision.estimatedBudget).toBeGreaterThan(0);
|
|
252
|
+
expect(decision.reasoning).toBeDefined();
|
|
253
|
+
expect(typeof decision.reasoning).toBe('string');
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it('should provide estimated budget based on strategy', async () => {
|
|
257
|
+
// Add high-quality playbook for low budget
|
|
258
|
+
await memory.playbooks.add({
|
|
259
|
+
id: 'pb-budget',
|
|
260
|
+
name: 'Quick fix',
|
|
261
|
+
applicability: {
|
|
262
|
+
situations: ['Quick budget test'],
|
|
263
|
+
triggers: ['budget test'],
|
|
264
|
+
antiPatterns: [],
|
|
265
|
+
domains: ['test'],
|
|
266
|
+
},
|
|
267
|
+
guidance: {
|
|
268
|
+
strategy: 'Simple fix',
|
|
269
|
+
tactics: [],
|
|
270
|
+
},
|
|
271
|
+
verification: {
|
|
272
|
+
successIndicators: ['Done'],
|
|
273
|
+
failureIndicators: [],
|
|
274
|
+
},
|
|
275
|
+
evolution: {
|
|
276
|
+
version: '1.0.0',
|
|
277
|
+
createdFrom: [],
|
|
278
|
+
failures: [],
|
|
279
|
+
refinements: [],
|
|
280
|
+
successCount: 5,
|
|
281
|
+
failureCount: 0,
|
|
282
|
+
},
|
|
283
|
+
confidence: 0.9,
|
|
284
|
+
complexity: 'simple',
|
|
285
|
+
estimatedEffort: 1,
|
|
286
|
+
createdAt: new Date(),
|
|
287
|
+
updatedAt: new Date(),
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const task = createTask({
|
|
291
|
+
domain: 'test',
|
|
292
|
+
description: 'Quick budget test task',
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const decision = await router.route(task);
|
|
296
|
+
|
|
297
|
+
// Direct strategy with high confidence should have low budget
|
|
298
|
+
if (decision.strategy === 'direct' && decision.confidence > 0.7) {
|
|
299
|
+
expect(decision.estimatedBudget).toBeLessThanOrEqual(4);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
describe('meta-learning integration', () => {
|
|
305
|
+
it('should apply meta-learning adjustments when metaLearner is set', async () => {
|
|
306
|
+
const mockMetaLearner: MetaLearner = {
|
|
307
|
+
adjustRouting: vi.fn().mockResolvedValue({
|
|
308
|
+
strategy: 'explore',
|
|
309
|
+
confidence: 0.7,
|
|
310
|
+
reasoning: 'Meta-adjusted reasoning',
|
|
311
|
+
}),
|
|
312
|
+
recordOutcome: vi.fn(),
|
|
313
|
+
getActiveGuidance: vi.fn().mockResolvedValue([]),
|
|
314
|
+
generateObservation: vi.fn(),
|
|
315
|
+
} as unknown as MetaLearner;
|
|
316
|
+
|
|
317
|
+
router.setMetaLearner(mockMetaLearner);
|
|
318
|
+
|
|
319
|
+
const task = createTask({
|
|
320
|
+
domain: 'test',
|
|
321
|
+
description: 'Meta-learning test task',
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
const decision = await router.route(task);
|
|
325
|
+
|
|
326
|
+
expect(mockMetaLearner.adjustRouting).toHaveBeenCalled();
|
|
327
|
+
// The decision should reflect meta-learning adjustment
|
|
328
|
+
expect(decision.strategy).toBe('explore');
|
|
329
|
+
expect(decision.appliedMetaStrategies).toContain('meta-learning adjustment');
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('should continue with base routing if meta-learning fails', async () => {
|
|
333
|
+
const failingMetaLearner: MetaLearner = {
|
|
334
|
+
adjustRouting: vi.fn().mockRejectedValue(new Error('Meta-learning failed')),
|
|
335
|
+
recordOutcome: vi.fn(),
|
|
336
|
+
getActiveGuidance: vi.fn().mockResolvedValue([]),
|
|
337
|
+
generateObservation: vi.fn(),
|
|
338
|
+
} as unknown as MetaLearner;
|
|
339
|
+
|
|
340
|
+
router.setMetaLearner(failingMetaLearner);
|
|
341
|
+
|
|
342
|
+
const task = createTask({
|
|
343
|
+
domain: 'test',
|
|
344
|
+
description: 'Failing meta test',
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Should not throw, should fall back to base routing
|
|
348
|
+
const decision = await router.route(task);
|
|
349
|
+
expect(decision).toBeDefined();
|
|
350
|
+
expect(decision.strategy).toBeDefined();
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
describe('task characteristics extraction', () => {
|
|
355
|
+
it('should identify bug fix tasks', async () => {
|
|
356
|
+
const task = createTask({
|
|
357
|
+
domain: 'code',
|
|
358
|
+
description: 'Fix the bug in user authentication',
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
const decision = await router.route(task);
|
|
362
|
+
expect(decision).toBeDefined();
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('should identify testing tasks', async () => {
|
|
366
|
+
const task = createTask({
|
|
367
|
+
domain: 'code',
|
|
368
|
+
description: 'Write unit tests for the payment service',
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
const decision = await router.route(task);
|
|
372
|
+
expect(decision).toBeDefined();
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it('should identify complex multi-file tasks', async () => {
|
|
376
|
+
const task = createTask({
|
|
377
|
+
domain: 'code',
|
|
378
|
+
description: 'Refactor authentication across multiple files in the codebase',
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
const decision = await router.route(task);
|
|
382
|
+
expect(decision).toBeDefined();
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
describe('createRouter', () => {
|
|
388
|
+
let tempDir: string;
|
|
389
|
+
let memory: MemorySystem;
|
|
390
|
+
|
|
391
|
+
beforeEach(async () => {
|
|
392
|
+
tempDir = await mkdtemp(join(tmpdir(), 'create-router-test-'));
|
|
393
|
+
memory = createMemorySystem(tempDir);
|
|
394
|
+
await memory.init();
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
afterEach(async () => {
|
|
398
|
+
await memory.close();
|
|
399
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it('should create a router with default config', () => {
|
|
403
|
+
const router = createRouter(memory);
|
|
404
|
+
expect(router).toBeInstanceOf(TaskRouter);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it('should create a router with custom config', () => {
|
|
408
|
+
const router = createRouter(memory, {
|
|
409
|
+
similarityThreshold: 0.7,
|
|
410
|
+
useDomainRouting: false,
|
|
411
|
+
defaultStrategy: 'explore',
|
|
412
|
+
});
|
|
413
|
+
expect(router).toBeInstanceOf(TaskRouter);
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('should create a router with meta learner', () => {
|
|
417
|
+
const mockMetaLearner = {
|
|
418
|
+
adjustRouting: vi.fn(),
|
|
419
|
+
recordOutcome: vi.fn(),
|
|
420
|
+
getActiveGuidance: vi.fn(),
|
|
421
|
+
generateObservation: vi.fn(),
|
|
422
|
+
} as unknown as MetaLearner;
|
|
423
|
+
|
|
424
|
+
const router = createRouter(memory, {}, mockMetaLearner);
|
|
425
|
+
expect(router).toBeInstanceOf(TaskRouter);
|
|
426
|
+
});
|
|
427
|
+
});
|