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/cli.js CHANGED
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import { parseArgs } from 'node:util';
17
17
  import { getProvider, listProviders } from './providers/index.js';
18
- import { run, list, pipe, init, add, update, remove, versions } from './commands/index.js';
18
+ import { run, list, pipe, init, add, update, remove, versions, compose, composeInfo } from './commands/index.js';
19
19
  const VERSION = '1.3.0';
20
20
  async function main() {
21
21
  const args = process.argv.slice(2);
@@ -48,6 +48,10 @@ async function main() {
48
48
  // Server options
49
49
  host: { type: 'string', short: 'H' },
50
50
  port: { type: 'string', short: 'P' },
51
+ // Compose options
52
+ 'max-depth': { type: 'string', short: 'd' },
53
+ timeout: { type: 'string', short: 'T' },
54
+ trace: { type: 'boolean', default: false },
51
55
  },
52
56
  allowPositionals: true,
53
57
  });
@@ -252,6 +256,45 @@ async function main() {
252
256
  }
253
257
  break;
254
258
  }
259
+ case 'compose': {
260
+ const moduleName = args[1];
261
+ if (!moduleName || moduleName.startsWith('-')) {
262
+ console.error('Usage: cog compose <module> [--args "..."] [--timeout <ms>] [--max-depth <n>]');
263
+ process.exit(1);
264
+ }
265
+ const result = await compose(moduleName, ctx, {
266
+ args: values.args,
267
+ input: values.input,
268
+ maxDepth: values['max-depth'] ? parseInt(values['max-depth'], 10) : undefined,
269
+ timeout: values.timeout ? parseInt(values.timeout, 10) : undefined,
270
+ trace: values.trace,
271
+ pretty: values.pretty,
272
+ verbose: values.verbose,
273
+ });
274
+ if (!result.success) {
275
+ console.error(`Error: ${result.error}`);
276
+ if (result.data) {
277
+ console.error('Partial results:', JSON.stringify(result.data, null, 2));
278
+ }
279
+ process.exit(1);
280
+ }
281
+ console.log(JSON.stringify(result.data, null, values.pretty ? 2 : 0));
282
+ break;
283
+ }
284
+ case 'compose-info': {
285
+ const moduleName = args[1];
286
+ if (!moduleName || moduleName.startsWith('-')) {
287
+ console.error('Usage: cog compose-info <module>');
288
+ process.exit(1);
289
+ }
290
+ const result = await composeInfo(moduleName, ctx);
291
+ if (!result.success) {
292
+ console.error(`Error: ${result.error}`);
293
+ process.exit(1);
294
+ }
295
+ console.log(JSON.stringify(result.data, null, 2));
296
+ break;
297
+ }
255
298
  case 'serve': {
256
299
  const { serve } = await import('./server/http.js');
257
300
  const port = values.port ? parseInt(values.port, 10) : 8000;
@@ -298,17 +341,19 @@ USAGE:
298
341
  cog <command> [options]
299
342
 
300
343
  COMMANDS:
301
- run <module> Run a Cognitive Module
302
- list List available modules
303
- add <url> Add module from GitHub
304
- update <module> Update module to latest version
305
- remove <module> Remove installed module
306
- versions <url> List available versions
307
- pipe Pipe mode (stdin/stdout)
308
- init [name] Initialize project or create module
309
- serve Start HTTP API server
310
- mcp Start MCP server (for Claude Code, Cursor)
311
- doctor Check configuration
344
+ run <module> Run a Cognitive Module
345
+ compose <module> Execute a composed module workflow
346
+ compose-info <mod> Show composition configuration
347
+ list List available modules
348
+ add <url> Add module from GitHub
349
+ update <module> Update module to latest version
350
+ remove <module> Remove installed module
351
+ versions <url> List available versions
352
+ pipe Pipe mode (stdin/stdout)
353
+ init [name] Initialize project or create module
354
+ serve Start HTTP API server
355
+ mcp Start MCP server (for Claude Code, Cursor)
356
+ doctor Check configuration
312
357
 
313
358
  OPTIONS:
314
359
  -a, --args <str> Arguments to pass to module
@@ -324,6 +369,9 @@ OPTIONS:
324
369
  --no-validate Skip schema validation
325
370
  -H, --host <host> Server host (default: 0.0.0.0)
326
371
  -P, --port <port> Server port (default: 8000)
372
+ -d, --max-depth <n> Max composition depth (default: 5)
373
+ -T, --timeout <ms> Composition timeout in milliseconds
374
+ --trace Include execution trace (for compose)
327
375
  -v, --version Show version
328
376
  -h, --help Show this help
329
377
 
@@ -342,6 +390,11 @@ EXAMPLES:
342
390
  cog run code-reviewer --provider openai --model gpt-4o --args "..."
343
391
  cog list
344
392
 
393
+ # Compose modules (multi-step workflows)
394
+ cog compose code-review-pipeline --args "code to review"
395
+ cog compose smart-processor --args "input" --timeout 60000 --verbose
396
+ cog compose-info code-review-pipeline
397
+
345
398
  # Servers
346
399
  cog serve --port 8080
347
400
  cog mcp
@@ -0,0 +1,31 @@
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
+ import type { CommandContext, CommandResult } from '../types.js';
11
+ export interface ComposeOptions {
12
+ /** Direct text input */
13
+ args?: string;
14
+ /** JSON input data */
15
+ input?: string;
16
+ /** Maximum composition depth */
17
+ maxDepth?: number;
18
+ /** Timeout in milliseconds */
19
+ timeout?: number;
20
+ /** Include execution trace */
21
+ trace?: boolean;
22
+ /** Pretty print output */
23
+ pretty?: boolean;
24
+ /** Verbose mode */
25
+ verbose?: boolean;
26
+ }
27
+ export declare function compose(moduleName: string, ctx: CommandContext, options?: ComposeOptions): Promise<CommandResult>;
28
+ /**
29
+ * Show composition info for a module
30
+ */
31
+ export declare function composeInfo(moduleName: string, ctx: CommandContext): Promise<CommandResult>;
@@ -0,0 +1,148 @@
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
+ import { findModule, getDefaultSearchPaths, executeComposition } from '../modules/index.js';
11
+ export async function compose(moduleName, ctx, options = {}) {
12
+ const searchPaths = getDefaultSearchPaths(ctx.cwd);
13
+ // Find module
14
+ const module = await findModule(moduleName, searchPaths);
15
+ if (!module) {
16
+ return {
17
+ success: false,
18
+ error: `Module not found: ${moduleName}\nSearch paths: ${searchPaths.join(', ')}`,
19
+ };
20
+ }
21
+ try {
22
+ // Parse input if provided as JSON
23
+ let inputData = {};
24
+ if (options.input) {
25
+ try {
26
+ inputData = JSON.parse(options.input);
27
+ }
28
+ catch {
29
+ return {
30
+ success: false,
31
+ error: `Invalid JSON input: ${options.input}`,
32
+ };
33
+ }
34
+ }
35
+ // Handle --args as text input
36
+ if (options.args) {
37
+ inputData.query = options.args;
38
+ inputData.code = options.args;
39
+ }
40
+ // Execute composition
41
+ const result = await executeComposition(moduleName, inputData, ctx.provider, {
42
+ cwd: ctx.cwd,
43
+ maxDepth: options.maxDepth,
44
+ timeoutMs: options.timeout
45
+ });
46
+ if (options.verbose) {
47
+ console.error('--- Composition Trace ---');
48
+ for (const entry of result.trace) {
49
+ const status = entry.success
50
+ ? (entry.skipped ? '⏭️ SKIPPED' : '✅ OK')
51
+ : '❌ FAILED';
52
+ console.error(`${status} ${entry.module} (${entry.durationMs}ms)`);
53
+ if (entry.reason) {
54
+ console.error(` Reason: ${entry.reason}`);
55
+ }
56
+ }
57
+ console.error(`--- Total: ${result.totalTimeMs}ms ---`);
58
+ }
59
+ // Return result
60
+ if (options.trace) {
61
+ // Include full result with trace
62
+ return {
63
+ success: result.ok,
64
+ data: {
65
+ ok: result.ok,
66
+ result: result.result,
67
+ moduleResults: result.moduleResults,
68
+ trace: result.trace,
69
+ totalTimeMs: result.totalTimeMs,
70
+ error: result.error
71
+ }
72
+ };
73
+ }
74
+ else if (options.pretty) {
75
+ return {
76
+ success: result.ok,
77
+ data: result.result,
78
+ };
79
+ }
80
+ else {
81
+ // For non-pretty mode, return data (success) or error (failure)
82
+ if (result.ok && result.result) {
83
+ return {
84
+ success: true,
85
+ data: result.result.data,
86
+ };
87
+ }
88
+ else {
89
+ return {
90
+ success: false,
91
+ error: result.error
92
+ ? `${result.error.code}: ${result.error.message}`
93
+ : 'Composition failed',
94
+ data: result.moduleResults,
95
+ };
96
+ }
97
+ }
98
+ }
99
+ catch (e) {
100
+ return {
101
+ success: false,
102
+ error: e instanceof Error ? e.message : String(e),
103
+ };
104
+ }
105
+ }
106
+ /**
107
+ * Show composition info for a module
108
+ */
109
+ export async function composeInfo(moduleName, ctx) {
110
+ const searchPaths = getDefaultSearchPaths(ctx.cwd);
111
+ const module = await findModule(moduleName, searchPaths);
112
+ if (!module) {
113
+ return {
114
+ success: false,
115
+ error: `Module not found: ${moduleName}`,
116
+ };
117
+ }
118
+ const composition = module.composition;
119
+ if (!composition) {
120
+ return {
121
+ success: true,
122
+ data: {
123
+ name: module.name,
124
+ hasComposition: false,
125
+ message: 'Module does not have composition configuration'
126
+ }
127
+ };
128
+ }
129
+ return {
130
+ success: true,
131
+ data: {
132
+ name: module.name,
133
+ hasComposition: true,
134
+ pattern: composition.pattern,
135
+ requires: composition.requires?.map(d => ({
136
+ name: d.name,
137
+ version: d.version,
138
+ optional: d.optional,
139
+ fallback: d.fallback
140
+ })),
141
+ dataflowSteps: composition.dataflow?.length ?? 0,
142
+ routingRules: composition.routing?.length ?? 0,
143
+ maxDepth: composition.max_depth,
144
+ timeoutMs: composition.timeout_ms,
145
+ iteration: composition.iteration
146
+ }
147
+ };
148
+ }
@@ -9,3 +9,4 @@ export * from './add.js';
9
9
  export * from './update.js';
10
10
  export * from './remove.js';
11
11
  export * from './versions.js';
12
+ export * from './compose.js';
@@ -9,3 +9,4 @@ export * from './add.js';
9
9
  export * from './update.js';
10
10
  export * from './remove.js';
11
11
  export * from './versions.js';
12
+ export * from './compose.js';
package/dist/index.d.ts CHANGED
@@ -3,9 +3,9 @@
3
3
  *
4
4
  * Exports all public APIs for programmatic use.
5
5
  */
6
- export type { Provider, InvokeParams, InvokeResult, Message, CognitiveModule, ModuleResult, ModuleInput, ModuleConstraints, ToolsPolicy, OutputContract, FailureContract, CommandContext, CommandResult, } from './types.js';
6
+ export type { Provider, InvokeParams, InvokeResult, Message, CognitiveModule, ModuleResult, ModuleInput, ModuleConstraints, ToolsPolicy, OutputContract, FailureContract, CommandContext, CommandResult, CompositionConfig, CompositionPattern, DependencyDeclaration, DataflowStep, DataflowMapping, RoutingRule, AggregationStrategy, IterationConfig, } from './types.js';
7
7
  export { getProvider, listProviders, GeminiProvider, OpenAIProvider, AnthropicProvider, BaseProvider, } from './providers/index.js';
8
- export { loadModule, findModule, listModules, getDefaultSearchPaths, runModule, SubagentOrchestrator, runWithSubagents, parseCalls, createContext, } from './modules/index.js';
8
+ export { loadModule, findModule, listModules, getDefaultSearchPaths, runModule, SubagentOrchestrator, runWithSubagents, parseCalls, createContext, CompositionOrchestrator, executeComposition, validateCompositionConfig, evaluateJsonPath, evaluateCondition, applyMapping, aggregateResults, versionMatches, resolveDependency, COMPOSITION_ERRORS, checkToolPolicy, checkPolicy, checkToolAllowed, validateToolsAllowed, getDeniedActions, getDeniedTools, getAllowedTools, ToolCallInterceptor, createPolicyAwareExecutor, type PolicyAction, type PolicyCheckResult, type ToolCallRequest, type ToolCallResult, type ToolExecutor, } from './modules/index.js';
9
9
  export { serve as serveHttp, createServer } from './server/index.js';
10
10
  export { serve as serveMcp } from './mcp/index.js';
11
11
  export { run, list, pipe } from './commands/index.js';
package/dist/index.js CHANGED
@@ -8,7 +8,11 @@ export { getProvider, listProviders, GeminiProvider, OpenAIProvider, AnthropicPr
8
8
  // Modules
9
9
  export { loadModule, findModule, listModules, getDefaultSearchPaths, runModule,
10
10
  // Subagent
11
- SubagentOrchestrator, runWithSubagents, parseCalls, createContext, } from './modules/index.js';
11
+ SubagentOrchestrator, runWithSubagents, parseCalls, createContext,
12
+ // Composition
13
+ CompositionOrchestrator, executeComposition, validateCompositionConfig, evaluateJsonPath, evaluateCondition, applyMapping, aggregateResults, versionMatches, resolveDependency, COMPOSITION_ERRORS,
14
+ // Policy Enforcement
15
+ checkToolPolicy, checkPolicy, checkToolAllowed, validateToolsAllowed, getDeniedActions, getDeniedTools, getAllowedTools, ToolCallInterceptor, createPolicyAwareExecutor, } from './modules/index.js';
12
16
  // Server
13
17
  export { serve as serveHttp, createServer } from './server/index.js';
14
18
  // MCP
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Composition Engine - Module Composition and Orchestration
3
+ *
4
+ * Implements COMPOSITION.md specification:
5
+ * - Sequential Composition: A → B → C
6
+ * - Parallel Composition: A → [B, C, D] → Aggregator
7
+ * - Conditional Composition: A → (condition) → B or C
8
+ * - Iterative Composition: A → (check) → A → ... → Done
9
+ * - Dataflow Mapping: JSONPath-like expressions
10
+ * - Aggregation Strategies: merge, array, first, custom
11
+ * - Dependency Resolution with fallbacks
12
+ * - Timeout handling
13
+ * - Circular dependency detection
14
+ */
15
+ import type { CognitiveModule, ModuleResult, ModuleInput, Provider } from '../types.js';
16
+ /** Composition pattern types */
17
+ export type CompositionPattern = 'sequential' | 'parallel' | 'conditional' | 'iterative';
18
+ /** Aggregation strategy for combining multiple outputs */
19
+ export type AggregationStrategy = 'merge' | 'array' | 'first' | 'custom';
20
+ /** Semver-like version matching pattern */
21
+ export type VersionPattern = string;
22
+ /** Dependency declaration for composition.requires */
23
+ export interface DependencyDeclaration {
24
+ /** Module name */
25
+ name: string;
26
+ /** Semver version pattern */
27
+ version?: VersionPattern;
28
+ /** Whether dependency is optional */
29
+ optional?: boolean;
30
+ /** Fallback module if unavailable */
31
+ fallback?: string | null;
32
+ /** Per-module timeout (ms) */
33
+ timeout_ms?: number;
34
+ }
35
+ /** Dataflow mapping expression */
36
+ export interface DataflowMapping {
37
+ [key: string]: string;
38
+ }
39
+ /** Condition expression for routing */
40
+ export interface ConditionExpression {
41
+ expression: string;
42
+ }
43
+ /** Dataflow step configuration */
44
+ export interface DataflowStep {
45
+ /** Source of data: 'input' or 'module-name.output' */
46
+ from: string | string[];
47
+ /** Destination: module name or 'output' */
48
+ to: string | string[];
49
+ /** Field mapping expressions */
50
+ mapping?: DataflowMapping;
51
+ /** Condition for execution */
52
+ condition?: string;
53
+ /** Aggregation strategy when from is an array */
54
+ aggregate?: AggregationStrategy;
55
+ /** Custom aggregation function name */
56
+ aggregator?: string;
57
+ }
58
+ /** Conditional routing rule */
59
+ export interface RoutingRule {
60
+ /** Condition expression */
61
+ condition: string;
62
+ /** Next module to execute (null means use current result) */
63
+ next: string | null;
64
+ }
65
+ /** Full composition configuration (from module.yaml) */
66
+ export interface CompositionConfig {
67
+ /** Composition pattern */
68
+ pattern: CompositionPattern;
69
+ /** Required dependencies */
70
+ requires?: DependencyDeclaration[];
71
+ /** Dataflow configuration */
72
+ dataflow?: DataflowStep[];
73
+ /** Conditional routing rules */
74
+ routing?: RoutingRule[];
75
+ /** Maximum composition depth */
76
+ max_depth?: number;
77
+ /** Total timeout for composition (ms) */
78
+ timeout_ms?: number;
79
+ /** Iteration configuration */
80
+ iteration?: {
81
+ /** Maximum iterations */
82
+ max_iterations?: number;
83
+ /** Condition to continue iterating */
84
+ continue_condition?: string;
85
+ /** Condition to stop iterating */
86
+ stop_condition?: string;
87
+ };
88
+ }
89
+ /** Execution context for composition */
90
+ export interface CompositionContext {
91
+ /** Current execution depth */
92
+ depth: number;
93
+ /** Maximum allowed depth */
94
+ maxDepth: number;
95
+ /** Results from completed modules */
96
+ results: Record<string, ModuleResult>;
97
+ /** Original input data */
98
+ input: ModuleInput;
99
+ /** Currently running modules (for circular detection) */
100
+ running: Set<string>;
101
+ /** Start time for timeout tracking */
102
+ startTime: number;
103
+ /** Total timeout (ms) */
104
+ timeoutMs?: number;
105
+ /** Iteration count (for iterative composition) */
106
+ iterationCount: number;
107
+ }
108
+ /** Result of composition execution */
109
+ export interface CompositionResult {
110
+ /** Whether composition succeeded */
111
+ ok: boolean;
112
+ /** Final aggregated result */
113
+ result?: ModuleResult;
114
+ /** Results from all executed modules */
115
+ moduleResults: Record<string, ModuleResult>;
116
+ /** Execution trace for debugging */
117
+ trace: ExecutionTrace[];
118
+ /** Total execution time (ms) */
119
+ totalTimeMs: number;
120
+ /** Error if composition failed */
121
+ error?: {
122
+ code: string;
123
+ message: string;
124
+ module?: string;
125
+ };
126
+ }
127
+ /** Execution trace entry */
128
+ export interface ExecutionTrace {
129
+ module: string;
130
+ startTime: number;
131
+ endTime: number;
132
+ durationMs: number;
133
+ success: boolean;
134
+ skipped?: boolean;
135
+ reason?: string;
136
+ }
137
+ export declare const COMPOSITION_ERRORS: {
138
+ readonly E4004: "CIRCULAR_DEPENDENCY";
139
+ readonly E4005: "MAX_DEPTH_EXCEEDED";
140
+ readonly E4008: "COMPOSITION_TIMEOUT";
141
+ readonly E4009: "DEPENDENCY_NOT_FOUND";
142
+ readonly E4010: "DATAFLOW_ERROR";
143
+ readonly E4011: "CONDITION_EVAL_ERROR";
144
+ readonly E4012: "AGGREGATION_ERROR";
145
+ readonly E4013: "ITERATION_LIMIT_EXCEEDED";
146
+ };
147
+ /**
148
+ * Parse and evaluate JSONPath-like expressions.
149
+ *
150
+ * Supported syntax:
151
+ * - $.field - Root field access
152
+ * - $.nested.field - Nested access
153
+ * - $.array[0] - Array index
154
+ * - $.array[*].field - Array map
155
+ * - $ - Entire object
156
+ */
157
+ export declare function evaluateJsonPath(expression: string, data: unknown): unknown;
158
+ /**
159
+ * Apply dataflow mapping to transform data
160
+ */
161
+ export declare function applyMapping(mapping: DataflowMapping, sourceData: unknown): Record<string, unknown>;
162
+ /**
163
+ * Evaluate condition expressions.
164
+ *
165
+ * Supported operators:
166
+ * - Comparison: ==, !=, >, <, >=, <=
167
+ * - Logical: &&, ||, !
168
+ * - Existence: exists($.field)
169
+ * - String: contains($.field, "value")
170
+ */
171
+ export declare function evaluateCondition(expression: string, data: unknown): boolean;
172
+ /**
173
+ * Aggregate multiple results using specified strategy
174
+ */
175
+ export declare function aggregateResults(results: ModuleResult[], strategy: AggregationStrategy): ModuleResult;
176
+ /**
177
+ * Check if version matches pattern (simplified semver)
178
+ */
179
+ export declare function versionMatches(version: string, pattern: string): boolean;
180
+ /**
181
+ * Resolve a dependency, checking version and trying fallbacks
182
+ */
183
+ export declare function resolveDependency(dep: DependencyDeclaration, searchPaths: string[]): Promise<CognitiveModule | null>;
184
+ export declare class CompositionOrchestrator {
185
+ private provider;
186
+ private cwd;
187
+ private searchPaths;
188
+ constructor(provider: Provider, cwd?: string);
189
+ /**
190
+ * Execute a composed module workflow
191
+ */
192
+ execute(moduleName: string, input: ModuleInput, options?: {
193
+ maxDepth?: number;
194
+ timeoutMs?: number;
195
+ }): Promise<CompositionResult>;
196
+ /**
197
+ * Get composition config from module (if exists)
198
+ */
199
+ private getCompositionConfig;
200
+ /**
201
+ * Execute composition based on pattern
202
+ */
203
+ private executeComposition;
204
+ /**
205
+ * Execute sequential composition: A → B → C
206
+ */
207
+ private executeSequential;
208
+ /**
209
+ * Execute parallel composition: A → [B, C, D] → Aggregator
210
+ */
211
+ private executeParallel;
212
+ /**
213
+ * Execute conditional composition: A → (condition) → B or C
214
+ */
215
+ private executeConditional;
216
+ /**
217
+ * Execute iterative composition: A → (check) → A → ... → Done
218
+ */
219
+ private executeIterative;
220
+ /**
221
+ * Execute a single module
222
+ */
223
+ private executeModule;
224
+ /**
225
+ * Execute module with timeout
226
+ */
227
+ private executeModuleWithTimeout;
228
+ /**
229
+ * Check if composition has timed out
230
+ */
231
+ private isTimedOut;
232
+ /**
233
+ * Create timeout error response
234
+ */
235
+ private timeoutError;
236
+ }
237
+ /**
238
+ * Execute a composed module workflow
239
+ */
240
+ export declare function executeComposition(moduleName: string, input: ModuleInput, provider: Provider, options?: {
241
+ cwd?: string;
242
+ maxDepth?: number;
243
+ timeoutMs?: number;
244
+ }): Promise<CompositionResult>;
245
+ /**
246
+ * Validate composition configuration
247
+ */
248
+ export declare function validateCompositionConfig(config: CompositionConfig): {
249
+ valid: boolean;
250
+ errors: string[];
251
+ };