cognitive-modules-cli 2.2.0 → 2.2.1

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/types.d.ts CHANGED
@@ -35,6 +35,77 @@ export type RiskLevel = 'none' | 'low' | 'medium' | 'high';
35
35
  export type EnumStrategy = 'strict' | 'extensible';
36
36
  /** Risk aggregation rule */
37
37
  export type RiskRule = 'max_changes_risk' | 'max_issues_risk' | 'explicit';
38
+ /** Composition pattern types */
39
+ export type CompositionPattern = 'sequential' | 'parallel' | 'conditional' | 'iterative';
40
+ /** Aggregation strategy for combining multiple outputs */
41
+ export type AggregationStrategy = 'merge' | 'array' | 'first' | 'custom';
42
+ /** Semver-like version matching pattern */
43
+ export type VersionPattern = string;
44
+ /** Dependency declaration for composition.requires */
45
+ export interface DependencyDeclaration {
46
+ /** Module name */
47
+ name: string;
48
+ /** Semver version pattern */
49
+ version?: VersionPattern;
50
+ /** Whether dependency is optional */
51
+ optional?: boolean;
52
+ /** Fallback module if unavailable */
53
+ fallback?: string | null;
54
+ /** Per-module timeout (ms) */
55
+ timeout_ms?: number;
56
+ }
57
+ /** Dataflow mapping expression */
58
+ export interface DataflowMapping {
59
+ [key: string]: string;
60
+ }
61
+ /** Dataflow step configuration */
62
+ export interface DataflowStep {
63
+ /** Source of data: 'input' or 'module-name.output' */
64
+ from: string | string[];
65
+ /** Destination: module name or 'output' */
66
+ to: string | string[];
67
+ /** Field mapping expressions */
68
+ mapping?: DataflowMapping;
69
+ /** Condition for execution */
70
+ condition?: string;
71
+ /** Aggregation strategy when from is an array */
72
+ aggregate?: AggregationStrategy;
73
+ /** Custom aggregation function name */
74
+ aggregator?: string;
75
+ }
76
+ /** Conditional routing rule */
77
+ export interface RoutingRule {
78
+ /** Condition expression */
79
+ condition: string;
80
+ /** Next module to execute (null means use current result) */
81
+ next: string | null;
82
+ }
83
+ /** Iteration configuration */
84
+ export interface IterationConfig {
85
+ /** Maximum iterations */
86
+ max_iterations?: number;
87
+ /** Condition to continue iterating */
88
+ continue_condition?: string;
89
+ /** Condition to stop iterating */
90
+ stop_condition?: string;
91
+ }
92
+ /** Full composition configuration (from module.yaml) */
93
+ export interface CompositionConfig {
94
+ /** Composition pattern */
95
+ pattern: CompositionPattern;
96
+ /** Required dependencies */
97
+ requires?: DependencyDeclaration[];
98
+ /** Dataflow configuration */
99
+ dataflow?: DataflowStep[];
100
+ /** Conditional routing rules */
101
+ routing?: RoutingRule[];
102
+ /** Maximum composition depth */
103
+ max_depth?: number;
104
+ /** Total timeout for composition (ms) */
105
+ timeout_ms?: number;
106
+ /** Iteration configuration */
107
+ iteration?: IterationConfig;
108
+ }
38
109
  export interface CognitiveModule {
39
110
  name: string;
40
111
  version: string;
@@ -52,6 +123,7 @@ export interface CognitiveModule {
52
123
  enums?: EnumConfig;
53
124
  compat?: CompatConfig;
54
125
  metaConfig?: MetaConfig;
126
+ composition?: CompositionConfig;
55
127
  context?: 'fork' | 'main';
56
128
  prompt: string;
57
129
  inputSchema?: object;
@@ -148,20 +220,34 @@ export interface EnvelopeMeta {
148
220
  /** Execution latency in milliseconds */
149
221
  latency_ms?: number;
150
222
  }
223
+ /**
224
+ * Enhanced error structure with retry and recovery info (v2.2.1).
225
+ */
226
+ export interface EnvelopeError {
227
+ /** Error code (e.g., "INVALID_INPUT", "PARSE_ERROR") */
228
+ code: string;
229
+ /** Human-readable error message */
230
+ message: string;
231
+ /** Whether the error can be retried */
232
+ recoverable?: boolean;
233
+ /** Suggested wait time before retry (in milliseconds) */
234
+ retry_after_ms?: number;
235
+ /** Additional error context */
236
+ details?: Record<string, unknown>;
237
+ }
151
238
  /** Success response in v2.2 envelope format */
152
239
  export interface EnvelopeSuccessV22<T = unknown> {
153
240
  ok: true;
241
+ version?: string;
154
242
  meta: EnvelopeMeta;
155
243
  data: T;
156
244
  }
157
245
  /** Error response in v2.2 envelope format */
158
246
  export interface EnvelopeErrorV22 {
159
247
  ok: false;
248
+ version?: string;
160
249
  meta: EnvelopeMeta;
161
- error: {
162
- code: string;
163
- message: string;
164
- };
250
+ error: EnvelopeError;
165
251
  partial_data?: unknown;
166
252
  }
167
253
  /** v2.2 envelope response (union type) */
@@ -217,12 +303,10 @@ export interface ModuleResultData {
217
303
  /** v2.2 module result with meta and data separation */
218
304
  export interface ModuleResultV22 {
219
305
  ok: boolean;
306
+ version?: string;
220
307
  meta: EnvelopeMeta;
221
308
  data?: ModuleResultData;
222
- error?: {
223
- code: string;
224
- message: string;
225
- };
309
+ error?: EnvelopeError;
226
310
  partial_data?: unknown;
227
311
  raw?: string;
228
312
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognitive-modules-cli",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "Cognitive Modules - Structured AI Task Execution with version management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -37,6 +37,7 @@
37
37
  "node": ">=18.0.0"
38
38
  },
39
39
  "dependencies": {
40
+ "ajv": "^8.12.0",
40
41
  "js-yaml": "^4.1.1"
41
42
  },
42
43
  "optionalDependencies": {
package/src/cli.ts CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { parseArgs } from 'node:util';
18
18
  import { getProvider, listProviders } from './providers/index.js';
19
- import { run, list, pipe, init, add, update, remove, versions } from './commands/index.js';
19
+ import { run, list, pipe, init, add, update, remove, versions, compose, composeInfo } from './commands/index.js';
20
20
  import type { CommandContext } from './types.js';
21
21
 
22
22
  const VERSION = '1.3.0';
@@ -55,6 +55,10 @@ async function main() {
55
55
  // Server options
56
56
  host: { type: 'string', short: 'H' },
57
57
  port: { type: 'string', short: 'P' },
58
+ // Compose options
59
+ 'max-depth': { type: 'string', short: 'd' },
60
+ timeout: { type: 'string', short: 'T' },
61
+ trace: { type: 'boolean', default: false },
58
62
  },
59
63
  allowPositionals: true,
60
64
  });
@@ -291,6 +295,53 @@ async function main() {
291
295
  break;
292
296
  }
293
297
 
298
+ case 'compose': {
299
+ const moduleName = args[1];
300
+ if (!moduleName || moduleName.startsWith('-')) {
301
+ console.error('Usage: cog compose <module> [--args "..."] [--timeout <ms>] [--max-depth <n>]');
302
+ process.exit(1);
303
+ }
304
+
305
+ const result = await compose(moduleName, ctx, {
306
+ args: values.args,
307
+ input: values.input,
308
+ maxDepth: values['max-depth'] ? parseInt(values['max-depth'] as string, 10) : undefined,
309
+ timeout: values.timeout ? parseInt(values.timeout as string, 10) : undefined,
310
+ trace: values.trace,
311
+ pretty: values.pretty,
312
+ verbose: values.verbose,
313
+ });
314
+
315
+ if (!result.success) {
316
+ console.error(`Error: ${result.error}`);
317
+ if (result.data) {
318
+ console.error('Partial results:', JSON.stringify(result.data, null, 2));
319
+ }
320
+ process.exit(1);
321
+ }
322
+
323
+ console.log(JSON.stringify(result.data, null, values.pretty ? 2 : 0));
324
+ break;
325
+ }
326
+
327
+ case 'compose-info': {
328
+ const moduleName = args[1];
329
+ if (!moduleName || moduleName.startsWith('-')) {
330
+ console.error('Usage: cog compose-info <module>');
331
+ process.exit(1);
332
+ }
333
+
334
+ const result = await composeInfo(moduleName, ctx);
335
+
336
+ if (!result.success) {
337
+ console.error(`Error: ${result.error}`);
338
+ process.exit(1);
339
+ }
340
+
341
+ console.log(JSON.stringify(result.data, null, 2));
342
+ break;
343
+ }
344
+
294
345
  case 'serve': {
295
346
  const { serve } = await import('./server/http.js');
296
347
  const port = values.port ? parseInt(values.port as string, 10) : 8000;
@@ -338,17 +389,19 @@ USAGE:
338
389
  cog <command> [options]
339
390
 
340
391
  COMMANDS:
341
- run <module> Run a Cognitive Module
342
- list List available modules
343
- add <url> Add module from GitHub
344
- update <module> Update module to latest version
345
- remove <module> Remove installed module
346
- versions <url> List available versions
347
- pipe Pipe mode (stdin/stdout)
348
- init [name] Initialize project or create module
349
- serve Start HTTP API server
350
- mcp Start MCP server (for Claude Code, Cursor)
351
- doctor Check configuration
392
+ run <module> Run a Cognitive Module
393
+ compose <module> Execute a composed module workflow
394
+ compose-info <mod> Show composition configuration
395
+ list List available modules
396
+ add <url> Add module from GitHub
397
+ update <module> Update module to latest version
398
+ remove <module> Remove installed module
399
+ versions <url> List available versions
400
+ pipe Pipe mode (stdin/stdout)
401
+ init [name] Initialize project or create module
402
+ serve Start HTTP API server
403
+ mcp Start MCP server (for Claude Code, Cursor)
404
+ doctor Check configuration
352
405
 
353
406
  OPTIONS:
354
407
  -a, --args <str> Arguments to pass to module
@@ -364,6 +417,9 @@ OPTIONS:
364
417
  --no-validate Skip schema validation
365
418
  -H, --host <host> Server host (default: 0.0.0.0)
366
419
  -P, --port <port> Server port (default: 8000)
420
+ -d, --max-depth <n> Max composition depth (default: 5)
421
+ -T, --timeout <ms> Composition timeout in milliseconds
422
+ --trace Include execution trace (for compose)
367
423
  -v, --version Show version
368
424
  -h, --help Show this help
369
425
 
@@ -382,6 +438,11 @@ EXAMPLES:
382
438
  cog run code-reviewer --provider openai --model gpt-4o --args "..."
383
439
  cog list
384
440
 
441
+ # Compose modules (multi-step workflows)
442
+ cog compose code-review-pipeline --args "code to review"
443
+ cog compose smart-processor --args "input" --timeout 60000 --verbose
444
+ cog compose-info code-review-pipeline
445
+
385
446
  # Servers
386
447
  cog serve --port 8080
387
448
  cog mcp
@@ -0,0 +1,185 @@
1
+ /**
2
+ * cog compose - Execute a Composed Cognitive Module Workflow
3
+ *
4
+ * Supports all composition patterns:
5
+ * - Sequential: A → B → C
6
+ * - Parallel: A → [B, C, D] → Aggregate
7
+ * - Conditional: A → (condition) → B or C
8
+ * - Iterative: A → (check) → A → ... → Done
9
+ */
10
+
11
+ import type { CommandContext, CommandResult } from '../types.js';
12
+ import { findModule, getDefaultSearchPaths, executeComposition } from '../modules/index.js';
13
+
14
+ export interface ComposeOptions {
15
+ /** Direct text input */
16
+ args?: string;
17
+ /** JSON input data */
18
+ input?: string;
19
+ /** Maximum composition depth */
20
+ maxDepth?: number;
21
+ /** Timeout in milliseconds */
22
+ timeout?: number;
23
+ /** Include execution trace */
24
+ trace?: boolean;
25
+ /** Pretty print output */
26
+ pretty?: boolean;
27
+ /** Verbose mode */
28
+ verbose?: boolean;
29
+ }
30
+
31
+ export async function compose(
32
+ moduleName: string,
33
+ ctx: CommandContext,
34
+ options: ComposeOptions = {}
35
+ ): Promise<CommandResult> {
36
+ const searchPaths = getDefaultSearchPaths(ctx.cwd);
37
+
38
+ // Find module
39
+ const module = await findModule(moduleName, searchPaths);
40
+ if (!module) {
41
+ return {
42
+ success: false,
43
+ error: `Module not found: ${moduleName}\nSearch paths: ${searchPaths.join(', ')}`,
44
+ };
45
+ }
46
+
47
+ try {
48
+ // Parse input if provided as JSON
49
+ let inputData: Record<string, unknown> = {};
50
+ if (options.input) {
51
+ try {
52
+ inputData = JSON.parse(options.input);
53
+ } catch {
54
+ return {
55
+ success: false,
56
+ error: `Invalid JSON input: ${options.input}`,
57
+ };
58
+ }
59
+ }
60
+
61
+ // Handle --args as text input
62
+ if (options.args) {
63
+ inputData.query = options.args;
64
+ inputData.code = options.args;
65
+ }
66
+
67
+ // Execute composition
68
+ const result = await executeComposition(
69
+ moduleName,
70
+ inputData,
71
+ ctx.provider,
72
+ {
73
+ cwd: ctx.cwd,
74
+ maxDepth: options.maxDepth,
75
+ timeoutMs: options.timeout
76
+ }
77
+ );
78
+
79
+ if (options.verbose) {
80
+ console.error('--- Composition Trace ---');
81
+ for (const entry of result.trace) {
82
+ const status = entry.success
83
+ ? (entry.skipped ? '⏭️ SKIPPED' : '✅ OK')
84
+ : '❌ FAILED';
85
+ console.error(`${status} ${entry.module} (${entry.durationMs}ms)`);
86
+ if (entry.reason) {
87
+ console.error(` Reason: ${entry.reason}`);
88
+ }
89
+ }
90
+ console.error(`--- Total: ${result.totalTimeMs}ms ---`);
91
+ }
92
+
93
+ // Return result
94
+ if (options.trace) {
95
+ // Include full result with trace
96
+ return {
97
+ success: result.ok,
98
+ data: {
99
+ ok: result.ok,
100
+ result: result.result,
101
+ moduleResults: result.moduleResults,
102
+ trace: result.trace,
103
+ totalTimeMs: result.totalTimeMs,
104
+ error: result.error
105
+ }
106
+ };
107
+ } else if (options.pretty) {
108
+ return {
109
+ success: result.ok,
110
+ data: result.result,
111
+ };
112
+ } else {
113
+ // For non-pretty mode, return data (success) or error (failure)
114
+ if (result.ok && result.result) {
115
+ return {
116
+ success: true,
117
+ data: (result.result as { data?: unknown }).data,
118
+ };
119
+ } else {
120
+ return {
121
+ success: false,
122
+ error: result.error
123
+ ? `${result.error.code}: ${result.error.message}`
124
+ : 'Composition failed',
125
+ data: result.moduleResults,
126
+ };
127
+ }
128
+ }
129
+ } catch (e) {
130
+ return {
131
+ success: false,
132
+ error: e instanceof Error ? e.message : String(e),
133
+ };
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Show composition info for a module
139
+ */
140
+ export async function composeInfo(
141
+ moduleName: string,
142
+ ctx: CommandContext
143
+ ): Promise<CommandResult> {
144
+ const searchPaths = getDefaultSearchPaths(ctx.cwd);
145
+
146
+ const module = await findModule(moduleName, searchPaths);
147
+ if (!module) {
148
+ return {
149
+ success: false,
150
+ error: `Module not found: ${moduleName}`,
151
+ };
152
+ }
153
+
154
+ const composition = module.composition;
155
+ if (!composition) {
156
+ return {
157
+ success: true,
158
+ data: {
159
+ name: module.name,
160
+ hasComposition: false,
161
+ message: 'Module does not have composition configuration'
162
+ }
163
+ };
164
+ }
165
+
166
+ return {
167
+ success: true,
168
+ data: {
169
+ name: module.name,
170
+ hasComposition: true,
171
+ pattern: composition.pattern,
172
+ requires: composition.requires?.map(d => ({
173
+ name: d.name,
174
+ version: d.version,
175
+ optional: d.optional,
176
+ fallback: d.fallback
177
+ })),
178
+ dataflowSteps: composition.dataflow?.length ?? 0,
179
+ routingRules: composition.routing?.length ?? 0,
180
+ maxDepth: composition.max_depth,
181
+ timeoutMs: composition.timeout_ms,
182
+ iteration: composition.iteration
183
+ }
184
+ };
185
+ }
@@ -10,3 +10,4 @@ export * from './add.js';
10
10
  export * from './update.js';
11
11
  export * from './remove.js';
12
12
  export * from './versions.js';
13
+ export * from './compose.js';
package/src/index.ts CHANGED
@@ -19,6 +19,15 @@ export type {
19
19
  FailureContract,
20
20
  CommandContext,
21
21
  CommandResult,
22
+ // v2.2 Composition Types
23
+ CompositionConfig,
24
+ CompositionPattern,
25
+ DependencyDeclaration,
26
+ DataflowStep,
27
+ DataflowMapping,
28
+ RoutingRule,
29
+ AggregationStrategy,
30
+ IterationConfig,
22
31
  } from './types.js';
23
32
 
24
33
  // Providers
@@ -43,6 +52,32 @@ export {
43
52
  runWithSubagents,
44
53
  parseCalls,
45
54
  createContext,
55
+ // Composition
56
+ CompositionOrchestrator,
57
+ executeComposition,
58
+ validateCompositionConfig,
59
+ evaluateJsonPath,
60
+ evaluateCondition,
61
+ applyMapping,
62
+ aggregateResults,
63
+ versionMatches,
64
+ resolveDependency,
65
+ COMPOSITION_ERRORS,
66
+ // Policy Enforcement
67
+ checkToolPolicy,
68
+ checkPolicy,
69
+ checkToolAllowed,
70
+ validateToolsAllowed,
71
+ getDeniedActions,
72
+ getDeniedTools,
73
+ getAllowedTools,
74
+ ToolCallInterceptor,
75
+ createPolicyAwareExecutor,
76
+ type PolicyAction,
77
+ type PolicyCheckResult,
78
+ type ToolCallRequest,
79
+ type ToolCallResult,
80
+ type ToolExecutor,
46
81
  } from './modules/index.js';
47
82
 
48
83
  // Server