cognitive-modules-cli 2.2.1 → 2.2.5
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 +11 -0
- package/LICENSE +21 -0
- package/README.md +35 -29
- package/dist/cli.js +513 -22
- package/dist/commands/add.d.ts +33 -14
- package/dist/commands/add.js +222 -13
- package/dist/commands/compose.js +60 -23
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.js +4 -0
- package/dist/commands/init.js +23 -1
- package/dist/commands/migrate.d.ts +30 -0
- package/dist/commands/migrate.js +650 -0
- package/dist/commands/pipe.d.ts +1 -0
- package/dist/commands/pipe.js +31 -11
- package/dist/commands/remove.js +33 -2
- package/dist/commands/run.d.ts +1 -0
- package/dist/commands/run.js +37 -27
- package/dist/commands/search.d.ts +28 -0
- package/dist/commands/search.js +143 -0
- package/dist/commands/test.d.ts +65 -0
- package/dist/commands/test.js +454 -0
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +106 -14
- package/dist/commands/validate.d.ts +36 -0
- package/dist/commands/validate.js +97 -0
- package/dist/errors/index.d.ts +218 -0
- package/dist/errors/index.js +412 -0
- package/dist/mcp/server.js +84 -79
- package/dist/modules/composition.js +97 -32
- package/dist/modules/loader.js +4 -2
- package/dist/modules/runner.d.ts +65 -0
- package/dist/modules/runner.js +293 -49
- package/dist/modules/subagent.d.ts +6 -1
- package/dist/modules/subagent.js +18 -13
- package/dist/modules/validator.js +14 -6
- package/dist/providers/anthropic.d.ts +15 -0
- package/dist/providers/anthropic.js +147 -5
- package/dist/providers/base.d.ts +11 -0
- package/dist/providers/base.js +18 -0
- package/dist/providers/gemini.d.ts +15 -0
- package/dist/providers/gemini.js +122 -5
- package/dist/providers/ollama.d.ts +15 -0
- package/dist/providers/ollama.js +111 -3
- package/dist/providers/openai.d.ts +11 -0
- package/dist/providers/openai.js +133 -0
- package/dist/registry/client.d.ts +204 -0
- package/dist/registry/client.js +356 -0
- package/dist/registry/index.d.ts +4 -0
- package/dist/registry/index.js +4 -0
- package/dist/server/http.js +173 -42
- package/dist/types.d.ts +32 -1
- package/dist/types.js +4 -1
- package/dist/version.d.ts +1 -0
- package/dist/version.js +4 -0
- package/package.json +31 -7
- package/dist/modules/composition.test.d.ts +0 -11
- package/dist/modules/composition.test.js +0 -450
- package/dist/modules/policy.test.d.ts +0 -10
- package/dist/modules/policy.test.js +0 -369
- package/src/cli.ts +0 -471
- package/src/commands/add.ts +0 -315
- package/src/commands/compose.ts +0 -185
- package/src/commands/index.ts +0 -13
- package/src/commands/init.ts +0 -94
- package/src/commands/list.ts +0 -33
- package/src/commands/pipe.ts +0 -76
- package/src/commands/remove.ts +0 -57
- package/src/commands/run.ts +0 -80
- package/src/commands/update.ts +0 -130
- package/src/commands/versions.ts +0 -79
- package/src/index.ts +0 -90
- package/src/mcp/index.ts +0 -5
- package/src/mcp/server.ts +0 -403
- package/src/modules/composition.test.ts +0 -558
- package/src/modules/composition.ts +0 -1674
- package/src/modules/index.ts +0 -9
- package/src/modules/loader.ts +0 -508
- package/src/modules/policy.test.ts +0 -455
- package/src/modules/runner.ts +0 -1983
- package/src/modules/subagent.ts +0 -277
- package/src/modules/validator.ts +0 -700
- package/src/providers/anthropic.ts +0 -89
- package/src/providers/base.ts +0 -29
- package/src/providers/deepseek.ts +0 -83
- package/src/providers/gemini.ts +0 -117
- package/src/providers/index.ts +0 -78
- package/src/providers/minimax.ts +0 -81
- package/src/providers/moonshot.ts +0 -82
- package/src/providers/ollama.ts +0 -83
- package/src/providers/openai.ts +0 -84
- package/src/providers/qwen.ts +0 -82
- package/src/server/http.ts +0 -316
- package/src/server/index.ts +0 -6
- package/src/types.ts +0 -599
- package/tsconfig.json +0 -17
package/dist/types.d.ts
CHANGED
|
@@ -6,6 +6,17 @@ export interface Provider {
|
|
|
6
6
|
name: string;
|
|
7
7
|
invoke(params: InvokeParams): Promise<InvokeResult>;
|
|
8
8
|
isConfigured(): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Stream-based invoke (optional).
|
|
11
|
+
* Returns an async generator that yields content chunks.
|
|
12
|
+
*
|
|
13
|
+
* If not implemented, falls back to non-streaming invoke.
|
|
14
|
+
*/
|
|
15
|
+
invokeStream?(params: InvokeParams): AsyncGenerator<string, InvokeResult, unknown>;
|
|
16
|
+
/**
|
|
17
|
+
* Check if this provider supports streaming.
|
|
18
|
+
*/
|
|
19
|
+
supportsStreaming?(): boolean;
|
|
9
20
|
}
|
|
10
21
|
export interface InvokeParams {
|
|
11
22
|
messages: Message[];
|
|
@@ -222,14 +233,19 @@ export interface EnvelopeMeta {
|
|
|
222
233
|
}
|
|
223
234
|
/**
|
|
224
235
|
* Enhanced error structure with retry and recovery info (v2.2.1).
|
|
236
|
+
*
|
|
237
|
+
* Consistent across HTTP, MCP, and CLI layers.
|
|
238
|
+
* See ERROR-CODES.md for error code taxonomy.
|
|
225
239
|
*/
|
|
226
240
|
export interface EnvelopeError {
|
|
227
|
-
/** Error code (
|
|
241
|
+
/** Error code (E-format like "E4006" or legacy like "MODULE_NOT_FOUND") */
|
|
228
242
|
code: string;
|
|
229
243
|
/** Human-readable error message */
|
|
230
244
|
message: string;
|
|
231
245
|
/** Whether the error can be retried */
|
|
232
246
|
recoverable?: boolean;
|
|
247
|
+
/** Suggested action to fix the error */
|
|
248
|
+
suggestion?: string;
|
|
233
249
|
/** Suggested wait time before retry (in milliseconds) */
|
|
234
250
|
retry_after_ms?: number;
|
|
235
251
|
/** Additional error context */
|
|
@@ -337,11 +353,26 @@ export interface CommandContext {
|
|
|
337
353
|
provider: Provider;
|
|
338
354
|
verbose?: boolean;
|
|
339
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* CLI command result (legacy format).
|
|
358
|
+
*
|
|
359
|
+
* For new code, prefer using CognitiveErrorEnvelope from errors/index.js
|
|
360
|
+
* for error responses to ensure cross-layer consistency.
|
|
361
|
+
*/
|
|
340
362
|
export interface CommandResult {
|
|
341
363
|
success: boolean;
|
|
342
364
|
data?: unknown;
|
|
343
365
|
error?: string;
|
|
344
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Extended command result with unified error structure.
|
|
369
|
+
* Use this for commands that need full error details.
|
|
370
|
+
*/
|
|
371
|
+
export interface CommandResultV2 {
|
|
372
|
+
ok: boolean;
|
|
373
|
+
data?: unknown;
|
|
374
|
+
error?: EnvelopeError;
|
|
375
|
+
}
|
|
345
376
|
export interface ModuleInput {
|
|
346
377
|
code?: string;
|
|
347
378
|
query?: string;
|
package/dist/types.js
CHANGED
|
@@ -44,7 +44,10 @@ function aggregateRiskFromList(items) {
|
|
|
44
44
|
}
|
|
45
45
|
let maxLevel = 0;
|
|
46
46
|
for (const item of items) {
|
|
47
|
-
const
|
|
47
|
+
const riskKey = item.risk;
|
|
48
|
+
const level = typeof riskKey === 'string' && Object.prototype.hasOwnProperty.call(riskLevels, riskKey)
|
|
49
|
+
? riskLevels[riskKey]
|
|
50
|
+
: riskLevels.medium;
|
|
48
51
|
maxLevel = Math.max(maxLevel, level);
|
|
49
52
|
}
|
|
50
53
|
return riskNames[maxLevel];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VERSION: string;
|
package/dist/version.js
ADDED
package/package.json
CHANGED
|
@@ -1,18 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognitive-modules-cli",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.5",
|
|
4
4
|
"description": "Cognitive Modules - Structured AI Task Execution with version management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
7
15
|
"bin": {
|
|
8
16
|
"cognitive-modules-cli": "dist/cli.js",
|
|
9
17
|
"cog": "dist/cli.js"
|
|
10
18
|
},
|
|
11
19
|
"scripts": {
|
|
12
|
-
"
|
|
20
|
+
"clean": "node -e \"import('node:fs').then(fs=>fs.rmSync('dist',{recursive:true,force:true}))\"",
|
|
21
|
+
"build": "npm run clean && tsc",
|
|
13
22
|
"start": "node dist/cli.js",
|
|
14
23
|
"dev": "tsx src/cli.ts",
|
|
15
|
-
"
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest",
|
|
26
|
+
"test:coverage": "vitest run --coverage",
|
|
27
|
+
"pack:check": "npm pack --dry-run --json --cache ../../.npm-cache",
|
|
28
|
+
"release:check": "npm run build && npm test && npm run pack:check",
|
|
29
|
+
"prepublishOnly": "npm run release:check"
|
|
16
30
|
},
|
|
17
31
|
"keywords": [
|
|
18
32
|
"cognitive",
|
|
@@ -25,13 +39,22 @@
|
|
|
25
39
|
],
|
|
26
40
|
"license": "MIT",
|
|
27
41
|
"author": "ziel-io",
|
|
42
|
+
"files": [
|
|
43
|
+
"dist",
|
|
44
|
+
"README.md",
|
|
45
|
+
"LICENSE",
|
|
46
|
+
"CHANGELOG.md"
|
|
47
|
+
],
|
|
28
48
|
"repository": {
|
|
29
49
|
"type": "git",
|
|
30
|
-
"url": "https://github.com/
|
|
50
|
+
"url": "https://github.com/Cognary/cognitive.git"
|
|
31
51
|
},
|
|
32
|
-
"homepage": "https://
|
|
52
|
+
"homepage": "https://cognary.github.io/cognitive/",
|
|
33
53
|
"bugs": {
|
|
34
|
-
"url": "https://github.com/
|
|
54
|
+
"url": "https://github.com/Cognary/cognitive/issues"
|
|
55
|
+
},
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public"
|
|
35
58
|
},
|
|
36
59
|
"engines": {
|
|
37
60
|
"node": ">=18.0.0"
|
|
@@ -47,6 +70,7 @@
|
|
|
47
70
|
"@types/js-yaml": "^4.0.9",
|
|
48
71
|
"@types/node": "^22.0.0",
|
|
49
72
|
"tsx": "^4.21.0",
|
|
50
|
-
"typescript": "^5.9.3"
|
|
73
|
+
"typescript": "^5.9.3",
|
|
74
|
+
"vitest": "^2.1.0"
|
|
51
75
|
}
|
|
52
76
|
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Composition Engine
|
|
3
|
-
*
|
|
4
|
-
* Tests all COMPOSITION.md specified functionality:
|
|
5
|
-
* - JSONPath-like expression evaluation
|
|
6
|
-
* - Condition expression evaluation
|
|
7
|
-
* - Aggregation strategies
|
|
8
|
-
* - Version matching
|
|
9
|
-
* - Sequential, Parallel, Conditional, Iterative patterns
|
|
10
|
-
*/
|
|
11
|
-
export {};
|
|
@@ -1,450 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Composition Engine
|
|
3
|
-
*
|
|
4
|
-
* Tests all COMPOSITION.md specified functionality:
|
|
5
|
-
* - JSONPath-like expression evaluation
|
|
6
|
-
* - Condition expression evaluation
|
|
7
|
-
* - Aggregation strategies
|
|
8
|
-
* - Version matching
|
|
9
|
-
* - Sequential, Parallel, Conditional, Iterative patterns
|
|
10
|
-
*/
|
|
11
|
-
import { describe, it, expect } from 'vitest';
|
|
12
|
-
import { evaluateJsonPath, evaluateCondition, applyMapping, aggregateResults, versionMatches, validateCompositionConfig, } from './composition.js';
|
|
13
|
-
// =============================================================================
|
|
14
|
-
// JSONPath Expression Tests
|
|
15
|
-
// =============================================================================
|
|
16
|
-
describe('evaluateJsonPath', () => {
|
|
17
|
-
const testData = {
|
|
18
|
-
name: 'test',
|
|
19
|
-
nested: {
|
|
20
|
-
value: 42,
|
|
21
|
-
deep: {
|
|
22
|
-
array: [1, 2, 3]
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
items: [
|
|
26
|
-
{ id: 1, name: 'a' },
|
|
27
|
-
{ id: 2, name: 'b' },
|
|
28
|
-
{ id: 3, name: 'c' }
|
|
29
|
-
],
|
|
30
|
-
meta: {
|
|
31
|
-
confidence: 0.95,
|
|
32
|
-
risk: 'low'
|
|
33
|
-
},
|
|
34
|
-
// Test hyphenated field names (Bug fix)
|
|
35
|
-
'quick-check': {
|
|
36
|
-
meta: {
|
|
37
|
-
confidence: 0.85
|
|
38
|
-
},
|
|
39
|
-
data: {
|
|
40
|
-
result: 'success'
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
it('should return entire object for $', () => {
|
|
45
|
-
expect(evaluateJsonPath('$', testData)).toEqual(testData);
|
|
46
|
-
});
|
|
47
|
-
it('should access root field with $.field', () => {
|
|
48
|
-
expect(evaluateJsonPath('$.name', testData)).toBe('test');
|
|
49
|
-
});
|
|
50
|
-
it('should access nested field with $.nested.field', () => {
|
|
51
|
-
expect(evaluateJsonPath('$.nested.value', testData)).toBe(42);
|
|
52
|
-
expect(evaluateJsonPath('$.nested.deep.array', testData)).toEqual([1, 2, 3]);
|
|
53
|
-
});
|
|
54
|
-
it('should access array index with $.array[0]', () => {
|
|
55
|
-
expect(evaluateJsonPath('$.items[0]', testData)).toEqual({ id: 1, name: 'a' });
|
|
56
|
-
expect(evaluateJsonPath('$.items[1].name', testData)).toBe('b');
|
|
57
|
-
expect(evaluateJsonPath('$.nested.deep.array[2]', testData)).toBe(3);
|
|
58
|
-
});
|
|
59
|
-
it('should map over array with $.array[*].field', () => {
|
|
60
|
-
expect(evaluateJsonPath('$.items[*].name', testData)).toEqual(['a', 'b', 'c']);
|
|
61
|
-
expect(evaluateJsonPath('$.items[*].id', testData)).toEqual([1, 2, 3]);
|
|
62
|
-
});
|
|
63
|
-
it('should return undefined for non-existent paths', () => {
|
|
64
|
-
expect(evaluateJsonPath('$.nonexistent', testData)).toBeUndefined();
|
|
65
|
-
expect(evaluateJsonPath('$.nested.nonexistent', testData)).toBeUndefined();
|
|
66
|
-
expect(evaluateJsonPath('$.items[99]', testData)).toBeUndefined();
|
|
67
|
-
});
|
|
68
|
-
it('should return literal values for non-JSONPath strings', () => {
|
|
69
|
-
expect(evaluateJsonPath('literal', testData)).toBe('literal');
|
|
70
|
-
expect(evaluateJsonPath('123', testData)).toBe('123');
|
|
71
|
-
});
|
|
72
|
-
it('should handle hyphenated field names', () => {
|
|
73
|
-
expect(evaluateJsonPath('$.quick-check.meta.confidence', testData)).toBe(0.85);
|
|
74
|
-
expect(evaluateJsonPath('$.quick-check.data.result', testData)).toBe('success');
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
// =============================================================================
|
|
78
|
-
// Condition Expression Tests
|
|
79
|
-
// =============================================================================
|
|
80
|
-
describe('evaluateCondition', () => {
|
|
81
|
-
const testData = {
|
|
82
|
-
meta: {
|
|
83
|
-
confidence: 0.85,
|
|
84
|
-
risk: 'low'
|
|
85
|
-
},
|
|
86
|
-
data: {
|
|
87
|
-
count: 5,
|
|
88
|
-
items: [1, 2, 3],
|
|
89
|
-
name: 'test module'
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
describe('comparison operators', () => {
|
|
93
|
-
it('should evaluate > operator', () => {
|
|
94
|
-
expect(evaluateCondition('$.meta.confidence > 0.7', testData)).toBe(true);
|
|
95
|
-
expect(evaluateCondition('$.meta.confidence > 0.9', testData)).toBe(false);
|
|
96
|
-
});
|
|
97
|
-
it('should evaluate < operator', () => {
|
|
98
|
-
expect(evaluateCondition('$.meta.confidence < 0.9', testData)).toBe(true);
|
|
99
|
-
expect(evaluateCondition('$.meta.confidence < 0.5', testData)).toBe(false);
|
|
100
|
-
});
|
|
101
|
-
it('should evaluate >= operator', () => {
|
|
102
|
-
expect(evaluateCondition('$.meta.confidence >= 0.85', testData)).toBe(true);
|
|
103
|
-
expect(evaluateCondition('$.meta.confidence >= 0.9', testData)).toBe(false);
|
|
104
|
-
});
|
|
105
|
-
it('should evaluate <= operator', () => {
|
|
106
|
-
expect(evaluateCondition('$.meta.confidence <= 0.85', testData)).toBe(true);
|
|
107
|
-
expect(evaluateCondition('$.meta.confidence <= 0.5', testData)).toBe(false);
|
|
108
|
-
});
|
|
109
|
-
it('should evaluate == operator', () => {
|
|
110
|
-
expect(evaluateCondition('$.meta.risk == "low"', testData)).toBe(true);
|
|
111
|
-
expect(evaluateCondition('$.meta.risk == "high"', testData)).toBe(false);
|
|
112
|
-
expect(evaluateCondition('$.data.count == 5', testData)).toBe(true);
|
|
113
|
-
});
|
|
114
|
-
it('should evaluate != operator', () => {
|
|
115
|
-
expect(evaluateCondition('$.meta.risk != "high"', testData)).toBe(true);
|
|
116
|
-
expect(evaluateCondition('$.meta.risk != "low"', testData)).toBe(false);
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
describe('logical operators', () => {
|
|
120
|
-
it('should evaluate && operator', () => {
|
|
121
|
-
expect(evaluateCondition('$.meta.confidence > 0.7 && $.meta.risk == "low"', testData)).toBe(true);
|
|
122
|
-
expect(evaluateCondition('$.meta.confidence > 0.9 && $.meta.risk == "low"', testData)).toBe(false);
|
|
123
|
-
});
|
|
124
|
-
it('should evaluate || operator', () => {
|
|
125
|
-
expect(evaluateCondition('$.meta.confidence > 0.9 || $.meta.risk == "low"', testData)).toBe(true);
|
|
126
|
-
expect(evaluateCondition('$.meta.confidence > 0.9 || $.meta.risk == "high"', testData)).toBe(false);
|
|
127
|
-
});
|
|
128
|
-
it('should evaluate ! operator', () => {
|
|
129
|
-
expect(evaluateCondition('!false', {})).toBe(true);
|
|
130
|
-
expect(evaluateCondition('!true', {})).toBe(false);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
describe('special functions', () => {
|
|
134
|
-
it('should evaluate exists() function', () => {
|
|
135
|
-
expect(evaluateCondition('exists($.meta.confidence)', testData)).toBe(true);
|
|
136
|
-
expect(evaluateCondition('exists($.meta.nonexistent)', testData)).toBe(false);
|
|
137
|
-
});
|
|
138
|
-
it('should evaluate .length property', () => {
|
|
139
|
-
expect(evaluateCondition('$.data.items.length > 0', testData)).toBe(true);
|
|
140
|
-
expect(evaluateCondition('$.data.items.length == 3', testData)).toBe(true);
|
|
141
|
-
});
|
|
142
|
-
it('should evaluate contains() for strings', () => {
|
|
143
|
-
expect(evaluateCondition('contains($.data.name, "test")', testData)).toBe(true);
|
|
144
|
-
expect(evaluateCondition('contains($.data.name, "xyz")', testData)).toBe(false);
|
|
145
|
-
});
|
|
146
|
-
it('should evaluate contains() for arrays', () => {
|
|
147
|
-
const dataWithArray = {
|
|
148
|
-
tags: ['javascript', 'typescript', 'node']
|
|
149
|
-
};
|
|
150
|
-
expect(evaluateCondition('contains($.tags, "typescript")', dataWithArray)).toBe(true);
|
|
151
|
-
expect(evaluateCondition('contains($.tags, "python")', dataWithArray)).toBe(false);
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
describe('hyphenated field names', () => {
|
|
155
|
-
const hyphenData = {
|
|
156
|
-
'quick-check': {
|
|
157
|
-
meta: { confidence: 0.85 },
|
|
158
|
-
data: { result: 'success' }
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
it('should handle hyphenated field names in conditions', () => {
|
|
162
|
-
expect(evaluateCondition('$.quick-check.meta.confidence > 0.8', hyphenData)).toBe(true);
|
|
163
|
-
expect(evaluateCondition('$.quick-check.meta.confidence > 0.9', hyphenData)).toBe(false);
|
|
164
|
-
});
|
|
165
|
-
it('should handle hyphenated fields with string comparison', () => {
|
|
166
|
-
expect(evaluateCondition('$.quick-check.data.result == "success"', hyphenData)).toBe(true);
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
// =============================================================================
|
|
171
|
-
// Dataflow Mapping Tests
|
|
172
|
-
// =============================================================================
|
|
173
|
-
describe('applyMapping', () => {
|
|
174
|
-
const sourceData = {
|
|
175
|
-
code: 'function test() {}',
|
|
176
|
-
language: 'javascript',
|
|
177
|
-
nested: {
|
|
178
|
-
value: 42
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
it('should map simple fields', () => {
|
|
182
|
-
const mapping = {
|
|
183
|
-
source_code: '$.code',
|
|
184
|
-
lang: '$.language'
|
|
185
|
-
};
|
|
186
|
-
const result = applyMapping(mapping, sourceData);
|
|
187
|
-
expect(result.source_code).toBe('function test() {}');
|
|
188
|
-
expect(result.lang).toBe('javascript');
|
|
189
|
-
});
|
|
190
|
-
it('should map nested fields', () => {
|
|
191
|
-
const mapping = {
|
|
192
|
-
extracted_value: '$.nested.value'
|
|
193
|
-
};
|
|
194
|
-
const result = applyMapping(mapping, sourceData);
|
|
195
|
-
expect(result.extracted_value).toBe(42);
|
|
196
|
-
});
|
|
197
|
-
it('should handle missing fields', () => {
|
|
198
|
-
const mapping = {
|
|
199
|
-
missing: '$.nonexistent'
|
|
200
|
-
};
|
|
201
|
-
const result = applyMapping(mapping, sourceData);
|
|
202
|
-
expect(result.missing).toBeUndefined();
|
|
203
|
-
});
|
|
204
|
-
it('should pass through entire object with $', () => {
|
|
205
|
-
const mapping = {
|
|
206
|
-
all: '$'
|
|
207
|
-
};
|
|
208
|
-
const result = applyMapping(mapping, sourceData);
|
|
209
|
-
expect(result.all).toEqual(sourceData);
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
// =============================================================================
|
|
213
|
-
// Aggregation Strategy Tests
|
|
214
|
-
// =============================================================================
|
|
215
|
-
describe('aggregateResults', () => {
|
|
216
|
-
const createResult = (data, confidence, risk) => ({
|
|
217
|
-
ok: true,
|
|
218
|
-
meta: {
|
|
219
|
-
confidence,
|
|
220
|
-
risk: risk,
|
|
221
|
-
explain: 'Test result'
|
|
222
|
-
},
|
|
223
|
-
data: {
|
|
224
|
-
...data,
|
|
225
|
-
rationale: 'Test rationale'
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
const results = [
|
|
229
|
-
createResult({ field1: 'value1', common: 'first' }, 0.8, 'low'),
|
|
230
|
-
createResult({ field2: 'value2', common: 'second' }, 0.9, 'medium'),
|
|
231
|
-
createResult({ field3: 'value3', common: 'third' }, 0.7, 'none')
|
|
232
|
-
];
|
|
233
|
-
describe('merge strategy', () => {
|
|
234
|
-
it('should deep merge all results (later wins)', () => {
|
|
235
|
-
const merged = aggregateResults(results, 'merge');
|
|
236
|
-
expect(merged.ok).toBe(true);
|
|
237
|
-
expect(merged.data.field1).toBe('value1');
|
|
238
|
-
expect(merged.data.field2).toBe('value2');
|
|
239
|
-
expect(merged.data.field3).toBe('value3');
|
|
240
|
-
expect(merged.data.common).toBe('third'); // Last wins
|
|
241
|
-
});
|
|
242
|
-
it('should aggregate meta values', () => {
|
|
243
|
-
const merged = aggregateResults(results, 'merge');
|
|
244
|
-
// Average confidence
|
|
245
|
-
expect(merged.meta.confidence).toBeCloseTo(0.8, 1);
|
|
246
|
-
// Max risk
|
|
247
|
-
expect(merged.meta.risk).toBe('medium');
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
describe('array strategy', () => {
|
|
251
|
-
it('should collect all results into array', () => {
|
|
252
|
-
const collected = aggregateResults(results, 'array');
|
|
253
|
-
expect(collected.ok).toBe(true);
|
|
254
|
-
const data = collected.data;
|
|
255
|
-
expect(data.results).toHaveLength(3);
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
describe('first strategy', () => {
|
|
259
|
-
it('should return first successful result', () => {
|
|
260
|
-
const first = aggregateResults(results, 'first');
|
|
261
|
-
expect(first.ok).toBe(true);
|
|
262
|
-
expect(first.data.field1).toBe('value1');
|
|
263
|
-
});
|
|
264
|
-
it('should skip failed results', () => {
|
|
265
|
-
const mixedResults = [
|
|
266
|
-
{
|
|
267
|
-
ok: false,
|
|
268
|
-
meta: { confidence: 0, risk: 'high', explain: 'Failed' },
|
|
269
|
-
error: { code: 'E1000', message: 'Error' }
|
|
270
|
-
},
|
|
271
|
-
createResult({ success: true }, 0.9, 'low')
|
|
272
|
-
];
|
|
273
|
-
const first = aggregateResults(mixedResults, 'first');
|
|
274
|
-
expect(first.ok).toBe(true);
|
|
275
|
-
expect(first.data.success).toBe(true);
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
describe('edge cases', () => {
|
|
279
|
-
it('should return error for empty results', () => {
|
|
280
|
-
const empty = aggregateResults([], 'merge');
|
|
281
|
-
expect(empty.ok).toBe(false);
|
|
282
|
-
});
|
|
283
|
-
it('should return single result unchanged', () => {
|
|
284
|
-
const single = aggregateResults([results[0]], 'merge');
|
|
285
|
-
expect(single).toEqual(results[0]);
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
});
|
|
289
|
-
// =============================================================================
|
|
290
|
-
// Version Matching Tests
|
|
291
|
-
// =============================================================================
|
|
292
|
-
describe('versionMatches', () => {
|
|
293
|
-
describe('exact version', () => {
|
|
294
|
-
it('should match exact version', () => {
|
|
295
|
-
expect(versionMatches('1.0.0', '1.0.0')).toBe(true);
|
|
296
|
-
expect(versionMatches('1.0.0', '1.0.1')).toBe(false);
|
|
297
|
-
expect(versionMatches('2.0.0', '1.0.0')).toBe(false);
|
|
298
|
-
});
|
|
299
|
-
});
|
|
300
|
-
describe('wildcard (*)', () => {
|
|
301
|
-
it('should match any version with *', () => {
|
|
302
|
-
expect(versionMatches('1.0.0', '*')).toBe(true);
|
|
303
|
-
expect(versionMatches('99.99.99', '*')).toBe(true);
|
|
304
|
-
});
|
|
305
|
-
it('should match any version with empty pattern', () => {
|
|
306
|
-
expect(versionMatches('1.0.0', '')).toBe(true);
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
|
-
describe('>= operator', () => {
|
|
310
|
-
it('should match versions greater than or equal', () => {
|
|
311
|
-
expect(versionMatches('1.0.0', '>=1.0.0')).toBe(true);
|
|
312
|
-
expect(versionMatches('1.1.0', '>=1.0.0')).toBe(true);
|
|
313
|
-
expect(versionMatches('2.0.0', '>=1.0.0')).toBe(true);
|
|
314
|
-
expect(versionMatches('0.9.0', '>=1.0.0')).toBe(false);
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
describe('> operator', () => {
|
|
318
|
-
it('should match versions strictly greater', () => {
|
|
319
|
-
expect(versionMatches('1.0.1', '>1.0.0')).toBe(true);
|
|
320
|
-
expect(versionMatches('1.1.0', '>1.0.0')).toBe(true);
|
|
321
|
-
expect(versionMatches('1.0.0', '>1.0.0')).toBe(false);
|
|
322
|
-
});
|
|
323
|
-
});
|
|
324
|
-
describe('^ (caret) operator', () => {
|
|
325
|
-
it('should match same major version', () => {
|
|
326
|
-
expect(versionMatches('1.2.3', '^1.0.0')).toBe(true);
|
|
327
|
-
expect(versionMatches('1.0.0', '^1.0.0')).toBe(true);
|
|
328
|
-
expect(versionMatches('2.0.0', '^1.0.0')).toBe(false);
|
|
329
|
-
expect(versionMatches('0.9.0', '^1.0.0')).toBe(false);
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
describe('~ (tilde) operator', () => {
|
|
333
|
-
it('should match same major.minor version', () => {
|
|
334
|
-
expect(versionMatches('1.0.5', '~1.0.0')).toBe(true);
|
|
335
|
-
expect(versionMatches('1.0.0', '~1.0.0')).toBe(true);
|
|
336
|
-
expect(versionMatches('1.1.0', '~1.0.0')).toBe(false);
|
|
337
|
-
expect(versionMatches('2.0.0', '~1.0.0')).toBe(false);
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
});
|
|
341
|
-
// =============================================================================
|
|
342
|
-
// Composition Config Validation Tests
|
|
343
|
-
// =============================================================================
|
|
344
|
-
describe('validateCompositionConfig', () => {
|
|
345
|
-
it('should validate correct sequential config', () => {
|
|
346
|
-
const config = {
|
|
347
|
-
pattern: 'sequential',
|
|
348
|
-
requires: [{ name: 'module-a' }],
|
|
349
|
-
dataflow: [
|
|
350
|
-
{ from: 'input', to: 'module-a' },
|
|
351
|
-
{ from: 'module-a.output', to: 'output' }
|
|
352
|
-
]
|
|
353
|
-
};
|
|
354
|
-
const result = validateCompositionConfig(config);
|
|
355
|
-
expect(result.valid).toBe(true);
|
|
356
|
-
expect(result.errors).toHaveLength(0);
|
|
357
|
-
});
|
|
358
|
-
it('should validate correct parallel config', () => {
|
|
359
|
-
const config = {
|
|
360
|
-
pattern: 'parallel',
|
|
361
|
-
requires: [
|
|
362
|
-
{ name: 'module-a' },
|
|
363
|
-
{ name: 'module-b' }
|
|
364
|
-
],
|
|
365
|
-
dataflow: [
|
|
366
|
-
{ from: 'input', to: ['module-a', 'module-b'] },
|
|
367
|
-
{ from: ['module-a.output', 'module-b.output'], to: 'output', aggregate: 'merge' }
|
|
368
|
-
]
|
|
369
|
-
};
|
|
370
|
-
const result = validateCompositionConfig(config);
|
|
371
|
-
expect(result.valid).toBe(true);
|
|
372
|
-
});
|
|
373
|
-
it('should require routing rules for conditional pattern', () => {
|
|
374
|
-
const config = {
|
|
375
|
-
pattern: 'conditional',
|
|
376
|
-
dataflow: [{ from: 'input', to: 'module-a' }]
|
|
377
|
-
};
|
|
378
|
-
const result = validateCompositionConfig(config);
|
|
379
|
-
expect(result.valid).toBe(false);
|
|
380
|
-
expect(result.errors.some(e => e.includes('routing'))).toBe(true);
|
|
381
|
-
});
|
|
382
|
-
it('should require iteration config for iterative pattern', () => {
|
|
383
|
-
const config = {
|
|
384
|
-
pattern: 'iterative',
|
|
385
|
-
dataflow: [{ from: 'input', to: 'module-a' }]
|
|
386
|
-
};
|
|
387
|
-
const result = validateCompositionConfig(config);
|
|
388
|
-
expect(result.valid).toBe(false);
|
|
389
|
-
expect(result.errors.some(e => e.includes('continue_condition') || e.includes('stop_condition'))).toBe(true);
|
|
390
|
-
});
|
|
391
|
-
it('should validate correct iterative config', () => {
|
|
392
|
-
const config = {
|
|
393
|
-
pattern: 'iterative',
|
|
394
|
-
iteration: {
|
|
395
|
-
max_iterations: 10,
|
|
396
|
-
stop_condition: '$.meta.confidence > 0.9'
|
|
397
|
-
}
|
|
398
|
-
};
|
|
399
|
-
const result = validateCompositionConfig(config);
|
|
400
|
-
expect(result.valid).toBe(true);
|
|
401
|
-
});
|
|
402
|
-
it('should detect invalid pattern', () => {
|
|
403
|
-
const config = {
|
|
404
|
-
pattern: 'invalid',
|
|
405
|
-
dataflow: []
|
|
406
|
-
};
|
|
407
|
-
const result = validateCompositionConfig(config);
|
|
408
|
-
expect(result.valid).toBe(false);
|
|
409
|
-
expect(result.errors.some(e => e.includes('Invalid pattern'))).toBe(true);
|
|
410
|
-
});
|
|
411
|
-
it('should detect missing dataflow fields', () => {
|
|
412
|
-
const config = {
|
|
413
|
-
pattern: 'sequential',
|
|
414
|
-
dataflow: [
|
|
415
|
-
{ from: 'input' },
|
|
416
|
-
]
|
|
417
|
-
};
|
|
418
|
-
const result = validateCompositionConfig(config);
|
|
419
|
-
expect(result.valid).toBe(false);
|
|
420
|
-
expect(result.errors.some(e => e.includes("missing 'to'"))).toBe(true);
|
|
421
|
-
});
|
|
422
|
-
});
|
|
423
|
-
// =============================================================================
|
|
424
|
-
// Integration Test Placeholders
|
|
425
|
-
// =============================================================================
|
|
426
|
-
describe('CompositionOrchestrator', () => {
|
|
427
|
-
// Note: Full integration tests require mocking Provider and modules
|
|
428
|
-
// These are placeholder tests that should be expanded with proper mocks
|
|
429
|
-
it.skip('should execute sequential composition', async () => {
|
|
430
|
-
// TODO: Add integration test with mocked provider
|
|
431
|
-
});
|
|
432
|
-
it.skip('should execute parallel composition', async () => {
|
|
433
|
-
// TODO: Add integration test with mocked provider
|
|
434
|
-
});
|
|
435
|
-
it.skip('should execute conditional composition', async () => {
|
|
436
|
-
// TODO: Add integration test with mocked provider
|
|
437
|
-
});
|
|
438
|
-
it.skip('should execute iterative composition', async () => {
|
|
439
|
-
// TODO: Add integration test with mocked provider
|
|
440
|
-
});
|
|
441
|
-
it.skip('should handle timeouts', async () => {
|
|
442
|
-
// TODO: Add timeout test
|
|
443
|
-
});
|
|
444
|
-
it.skip('should detect circular dependencies', async () => {
|
|
445
|
-
// TODO: Add circular dependency test
|
|
446
|
-
});
|
|
447
|
-
it.skip('should use fallback modules', async () => {
|
|
448
|
-
// TODO: Add fallback test
|
|
449
|
-
});
|
|
450
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Policy Enforcement
|
|
3
|
-
*
|
|
4
|
-
* Tests all policy enforcement functionality:
|
|
5
|
-
* - Tool policy checking (allowed/denied lists)
|
|
6
|
-
* - General policy checking (network, filesystem, etc.)
|
|
7
|
-
* - Tool call interception
|
|
8
|
-
* - Policy-aware executors
|
|
9
|
-
*/
|
|
10
|
-
export {};
|