cognitive-modules-cli 2.2.1 → 2.2.7

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.
Files changed (101) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +35 -29
  4. package/dist/cli.js +519 -23
  5. package/dist/commands/add.d.ts +33 -14
  6. package/dist/commands/add.js +383 -16
  7. package/dist/commands/compose.js +60 -23
  8. package/dist/commands/index.d.ts +4 -0
  9. package/dist/commands/index.js +4 -0
  10. package/dist/commands/init.js +23 -1
  11. package/dist/commands/migrate.d.ts +30 -0
  12. package/dist/commands/migrate.js +650 -0
  13. package/dist/commands/pipe.d.ts +1 -0
  14. package/dist/commands/pipe.js +31 -11
  15. package/dist/commands/remove.js +33 -2
  16. package/dist/commands/run.d.ts +2 -0
  17. package/dist/commands/run.js +61 -28
  18. package/dist/commands/search.d.ts +28 -0
  19. package/dist/commands/search.js +143 -0
  20. package/dist/commands/test.d.ts +65 -0
  21. package/dist/commands/test.js +454 -0
  22. package/dist/commands/update.d.ts +1 -0
  23. package/dist/commands/update.js +106 -14
  24. package/dist/commands/validate.d.ts +36 -0
  25. package/dist/commands/validate.js +97 -0
  26. package/dist/errors/index.d.ts +225 -0
  27. package/dist/errors/index.js +420 -0
  28. package/dist/mcp/server.js +84 -79
  29. package/dist/modules/composition.js +97 -32
  30. package/dist/modules/loader.js +4 -2
  31. package/dist/modules/runner.d.ts +72 -5
  32. package/dist/modules/runner.js +306 -59
  33. package/dist/modules/subagent.d.ts +6 -1
  34. package/dist/modules/subagent.js +18 -13
  35. package/dist/modules/validator.js +14 -6
  36. package/dist/providers/anthropic.d.ts +15 -0
  37. package/dist/providers/anthropic.js +147 -5
  38. package/dist/providers/base.d.ts +11 -0
  39. package/dist/providers/base.js +18 -0
  40. package/dist/providers/gemini.d.ts +15 -0
  41. package/dist/providers/gemini.js +122 -5
  42. package/dist/providers/ollama.d.ts +15 -0
  43. package/dist/providers/ollama.js +111 -3
  44. package/dist/providers/openai.d.ts +11 -0
  45. package/dist/providers/openai.js +133 -0
  46. package/dist/registry/client.d.ts +212 -0
  47. package/dist/registry/client.js +359 -0
  48. package/dist/registry/index.d.ts +4 -0
  49. package/dist/registry/index.js +4 -0
  50. package/dist/registry/tar.d.ts +8 -0
  51. package/dist/registry/tar.js +353 -0
  52. package/dist/server/http.js +301 -45
  53. package/dist/server/index.d.ts +2 -0
  54. package/dist/server/index.js +1 -0
  55. package/dist/server/sse.d.ts +13 -0
  56. package/dist/server/sse.js +22 -0
  57. package/dist/types.d.ts +32 -1
  58. package/dist/types.js +4 -1
  59. package/dist/version.d.ts +1 -0
  60. package/dist/version.js +4 -0
  61. package/package.json +31 -7
  62. package/dist/modules/composition.test.d.ts +0 -11
  63. package/dist/modules/composition.test.js +0 -450
  64. package/dist/modules/policy.test.d.ts +0 -10
  65. package/dist/modules/policy.test.js +0 -369
  66. package/src/cli.ts +0 -471
  67. package/src/commands/add.ts +0 -315
  68. package/src/commands/compose.ts +0 -185
  69. package/src/commands/index.ts +0 -13
  70. package/src/commands/init.ts +0 -94
  71. package/src/commands/list.ts +0 -33
  72. package/src/commands/pipe.ts +0 -76
  73. package/src/commands/remove.ts +0 -57
  74. package/src/commands/run.ts +0 -80
  75. package/src/commands/update.ts +0 -130
  76. package/src/commands/versions.ts +0 -79
  77. package/src/index.ts +0 -90
  78. package/src/mcp/index.ts +0 -5
  79. package/src/mcp/server.ts +0 -403
  80. package/src/modules/composition.test.ts +0 -558
  81. package/src/modules/composition.ts +0 -1674
  82. package/src/modules/index.ts +0 -9
  83. package/src/modules/loader.ts +0 -508
  84. package/src/modules/policy.test.ts +0 -455
  85. package/src/modules/runner.ts +0 -1983
  86. package/src/modules/subagent.ts +0 -277
  87. package/src/modules/validator.ts +0 -700
  88. package/src/providers/anthropic.ts +0 -89
  89. package/src/providers/base.ts +0 -29
  90. package/src/providers/deepseek.ts +0 -83
  91. package/src/providers/gemini.ts +0 -117
  92. package/src/providers/index.ts +0 -78
  93. package/src/providers/minimax.ts +0 -81
  94. package/src/providers/moonshot.ts +0 -82
  95. package/src/providers/ollama.ts +0 -83
  96. package/src/providers/openai.ts +0 -84
  97. package/src/providers/qwen.ts +0 -82
  98. package/src/server/http.ts +0 -316
  99. package/src/server/index.ts +0 -6
  100. package/src/types.ts +0 -599
  101. package/tsconfig.json +0 -17
@@ -401,9 +401,12 @@ export function aggregateResults(results, strategy) {
401
401
  const avgConfidence = allMeta.length > 0
402
402
  ? allMeta.reduce((sum, m) => sum + m.confidence, 0) / allMeta.length
403
403
  : 0.5;
404
- const maxRisk = allMeta.length > 0
405
- ? ['none', 'low', 'medium', 'high'][Math.max(...allMeta.map(m => ['none', 'low', 'medium', 'high'].indexOf(m.risk)))]
406
- : 'medium';
404
+ const riskLevels = { none: 0, low: 1, medium: 2, high: 3 };
405
+ const riskNames = ['none', 'low', 'medium', 'high'];
406
+ const maxRiskLevel = allMeta.length > 0
407
+ ? Math.max(...allMeta.map(m => riskLevels[m.risk] ?? 2))
408
+ : 2;
409
+ const maxRisk = riskNames[maxRiskLevel];
407
410
  return {
408
411
  ok: true,
409
412
  meta: {
@@ -502,6 +505,28 @@ export function versionMatches(version, pattern) {
502
505
  }
503
506
  return false;
504
507
  }
508
+ // <= match
509
+ if (pattern.startsWith('<=')) {
510
+ const pParts = parseVersion(pattern.slice(2));
511
+ for (let i = 0; i < 3; i++) {
512
+ if (vParts[i] < pParts[i])
513
+ return true;
514
+ if (vParts[i] > pParts[i])
515
+ return false;
516
+ }
517
+ return true;
518
+ }
519
+ // < match
520
+ if (pattern.startsWith('<') && !pattern.startsWith('<=')) {
521
+ const pParts = parseVersion(pattern.slice(1));
522
+ for (let i = 0; i < 3; i++) {
523
+ if (vParts[i] < pParts[i])
524
+ return true;
525
+ if (vParts[i] > pParts[i])
526
+ return false;
527
+ }
528
+ return false;
529
+ }
505
530
  // ^ (compatible) - same major
506
531
  if (pattern.startsWith('^')) {
507
532
  const pParts = parseVersion(pattern.slice(1));
@@ -816,18 +841,28 @@ export class CompositionOrchestrator {
816
841
  let sourceData = context.input;
817
842
  if (step.from) {
818
843
  const sources = Array.isArray(step.from) ? step.from : [step.from];
844
+ const sourceDataArray = [];
819
845
  for (const source of sources) {
820
846
  if (source === 'input') {
821
- sourceData = context.input;
847
+ sourceDataArray.push(context.input);
822
848
  }
823
849
  else {
824
850
  const moduleName = source.replace('.output', '');
825
851
  const moduleResult = context.results[moduleName];
826
852
  if (moduleResult && 'data' in moduleResult) {
827
- sourceData = moduleResult.data;
853
+ sourceDataArray.push(moduleResult.data);
828
854
  }
829
855
  }
830
856
  }
857
+ if (sourceDataArray.length === 1) {
858
+ sourceData = sourceDataArray[0];
859
+ }
860
+ else if (sourceDataArray.length > 1) {
861
+ sourceData = { sources: sourceDataArray };
862
+ }
863
+ else {
864
+ sourceData = context.input;
865
+ }
831
866
  }
832
867
  // Apply mapping
833
868
  if (step.mapping) {
@@ -866,6 +901,25 @@ export class CompositionOrchestrator {
866
901
  for (let i = 0; i < parallelModules.length; i++) {
867
902
  context.results[parallelModules[i]] = parallelResults[i];
868
903
  }
904
+ // Attempt fallbacks for failed modules
905
+ for (let i = 0; i < parallelModules.length; i++) {
906
+ const result = parallelResults[i];
907
+ if (result.ok)
908
+ continue;
909
+ const name = parallelModules[i];
910
+ const depConfig = composition.requires?.find(d => d.name === name);
911
+ const fallbackName = depConfig?.fallback;
912
+ if (!fallbackName)
913
+ continue;
914
+ const fallbackModule = await findModule(fallbackName, this.searchPaths);
915
+ if (!fallbackModule)
916
+ continue;
917
+ const depTimeout = depConfig?.timeout_ms;
918
+ const fallbackResult = await this.executeModuleWithTimeout(fallbackModule, sourceData, context, trace, depTimeout);
919
+ parallelResults[i] = fallbackResult;
920
+ context.results[fallbackName] = fallbackResult;
921
+ context.results[name] = fallbackResult;
922
+ }
869
923
  // Check for failures
870
924
  const failures = parallelResults.filter(r => !r.ok);
871
925
  if (failures.length > 0) {
@@ -1146,38 +1200,49 @@ export class CompositionOrchestrator {
1146
1200
  */
1147
1201
  async executeModuleWithTimeout(module, input, context, trace, timeoutMs) {
1148
1202
  const timeout = timeoutMs ?? context.timeoutMs;
1203
+ const localTrace = [];
1204
+ const localContext = {
1205
+ ...context,
1206
+ running: new Set(context.running),
1207
+ results: { ...context.results },
1208
+ };
1209
+ const startTime = Date.now();
1210
+ const execPromise = this.executeModule(module, input, localContext, localTrace);
1149
1211
  if (!timeout) {
1150
- return this.executeModule(module, input, context, trace);
1212
+ const result = await execPromise;
1213
+ trace.push(...localTrace);
1214
+ return result;
1151
1215
  }
1152
1216
  let timeoutId = null;
1153
- const timeoutPromise = new Promise((_, reject) => {
1154
- timeoutId = setTimeout(() => {
1155
- reject(new Error(`Module ${module.name} timed out after ${timeout}ms`));
1156
- }, timeout);
1217
+ const timeoutPromise = new Promise((resolve) => {
1218
+ timeoutId = setTimeout(() => resolve({ type: 'timeout' }), timeout);
1157
1219
  });
1158
- try {
1159
- const result = await Promise.race([
1160
- this.executeModule(module, input, context, trace),
1161
- timeoutPromise
1162
- ]);
1163
- // Clear timeout on success to prevent memory leak
1164
- if (timeoutId)
1165
- clearTimeout(timeoutId);
1166
- return result;
1167
- }
1168
- catch (error) {
1169
- // Clear timeout on error too
1170
- if (timeoutId)
1171
- clearTimeout(timeoutId);
1172
- return {
1173
- ok: false,
1174
- meta: { confidence: 0, risk: 'high', explain: `Timeout: ${module.name}` },
1175
- error: {
1176
- code: COMPOSITION_ERRORS.E4008,
1177
- message: error.message
1178
- }
1179
- };
1220
+ const raceResult = await Promise.race([
1221
+ execPromise.then(result => ({ type: 'result', result })),
1222
+ timeoutPromise
1223
+ ]);
1224
+ if (timeoutId)
1225
+ clearTimeout(timeoutId);
1226
+ if ('result' in raceResult) {
1227
+ trace.push(...localTrace);
1228
+ return raceResult.result;
1180
1229
  }
1230
+ trace.push({
1231
+ module: module.name,
1232
+ startTime,
1233
+ endTime: Date.now(),
1234
+ durationMs: Date.now() - startTime,
1235
+ success: false,
1236
+ reason: `Timeout after ${timeout}ms`
1237
+ });
1238
+ return {
1239
+ ok: false,
1240
+ meta: { confidence: 0, risk: 'high', explain: `Timeout: ${module.name}` },
1241
+ error: {
1242
+ code: COMPOSITION_ERRORS.E4008,
1243
+ message: `Module ${module.name} timed out after ${timeout}ms`
1244
+ }
1245
+ };
1181
1246
  }
1182
1247
  /**
1183
1248
  * Check if composition has timed out
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import * as fs from 'node:fs/promises';
6
6
  import * as path from 'node:path';
7
+ import { homedir } from 'node:os';
7
8
  import yaml from 'js-yaml';
8
9
  const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n([\s\S]*))?/;
9
10
  /**
@@ -54,7 +55,8 @@ async function loadModuleV2(modulePath) {
54
55
  const schemaFile = path.join(modulePath, 'schema.json');
55
56
  // Read module.yaml
56
57
  const manifestContent = await fs.readFile(manifestFile, 'utf-8');
57
- const manifest = yaml.load(manifestContent);
58
+ const loaded = yaml.load(manifestContent);
59
+ const manifest = loaded && typeof loaded === 'object' ? loaded : {};
58
60
  // Detect v2.x version
59
61
  const formatVersion = detectV2Version(manifest);
60
62
  // Read prompt.md
@@ -394,7 +396,7 @@ export async function listModules(searchPaths) {
394
396
  return modules;
395
397
  }
396
398
  export function getDefaultSearchPaths(cwd) {
397
- const home = process.env.HOME || '';
399
+ const home = homedir();
398
400
  return [
399
401
  path.join(cwd, 'cognitive', 'modules'),
400
402
  path.join(cwd, '.cognitive', 'modules'),
@@ -257,12 +257,69 @@ export declare function unregisterHook(hookType: 'before_call' | 'after_call' |
257
257
  * Clear all registered hooks.
258
258
  */
259
259
  export declare function clearHooks(): void;
260
+ /**
261
+ * Error code taxonomy following CONFORMANCE.md E1xxx-E4xxx structure.
262
+ *
263
+ * E1xxx: Input errors (caller errors, fixable by modifying input)
264
+ * E2xxx: Processing errors (module understood input but couldn't complete)
265
+ * E3xxx: Output errors (generated output doesn't meet requirements)
266
+ * E4xxx: Runtime errors (infrastructure/system-level failures)
267
+ */
268
+ /** Standard error codes with E-format (as per ERROR-CODES.md) */
269
+ export declare const ERROR_CODES: {
270
+ readonly E1000: "PARSE_ERROR";
271
+ readonly E1001: "INVALID_INPUT";
272
+ readonly E1002: "MISSING_REQUIRED_FIELD";
273
+ readonly E1003: "TYPE_MISMATCH";
274
+ readonly E1004: "UNSUPPORTED_VALUE";
275
+ readonly E1005: "INPUT_TOO_LARGE";
276
+ readonly E1006: "INVALID_REFERENCE";
277
+ readonly E2001: "LOW_CONFIDENCE";
278
+ readonly E2002: "TIMEOUT";
279
+ readonly E2003: "TOKEN_LIMIT";
280
+ readonly E2004: "NO_ACTION_POSSIBLE";
281
+ readonly E2005: "SEMANTIC_CONFLICT";
282
+ readonly E2006: "AMBIGUOUS_INPUT";
283
+ readonly E2007: "INSUFFICIENT_CONTEXT";
284
+ readonly E3001: "OUTPUT_SCHEMA_VIOLATION";
285
+ readonly E3002: "PARTIAL_RESULT";
286
+ readonly E3003: "MISSING_RATIONALE";
287
+ readonly E3004: "OVERFLOW_LIMIT";
288
+ readonly E3005: "INVALID_ENUM";
289
+ readonly E3006: "CONSTRAINT_VIOLATION";
290
+ readonly E4000: "INTERNAL_ERROR";
291
+ readonly E4001: "PROVIDER_UNAVAILABLE";
292
+ readonly E4002: "RATE_LIMITED";
293
+ readonly E4003: "CONTEXT_OVERFLOW";
294
+ readonly E4004: "CIRCULAR_DEPENDENCY";
295
+ readonly E4005: "MAX_DEPTH_EXCEEDED";
296
+ readonly E4006: "MODULE_NOT_FOUND";
297
+ readonly E4007: "PERMISSION_DENIED";
298
+ };
299
+ /** Reverse mapping: legacy code -> E-format code */
300
+ export declare const LEGACY_TO_E_CODE: Record<string, string>;
260
301
  /** Error codes and their default properties */
261
302
  export declare const ERROR_PROPERTIES: Record<string, {
262
303
  recoverable: boolean;
263
304
  retry_after_ms: number | null;
264
305
  }>;
306
+ /**
307
+ * Normalize error code to E-format.
308
+ * Accepts both E-format (E1001) and legacy format (INVALID_INPUT).
309
+ *
310
+ * @param code Error code in any format
311
+ * @returns E-format code (e.g., "E1001")
312
+ */
313
+ export declare function normalizeErrorCode(code: string): string;
314
+ /**
315
+ * Get error category from E-format code.
316
+ *
317
+ * @param code E-format error code (e.g., "E1001")
318
+ * @returns Category: 'input' | 'processing' | 'output' | 'runtime'
319
+ */
320
+ export declare function getErrorCategory(code: string): 'input' | 'processing' | 'output' | 'runtime';
265
321
  export interface MakeErrorResponseOptions {
322
+ /** Error code - accepts both E-format (E1001) and legacy format (INVALID_INPUT) */
266
323
  code: string;
267
324
  message: string;
268
325
  explain?: string;
@@ -272,9 +329,17 @@ export interface MakeErrorResponseOptions {
272
329
  retryAfterMs?: number;
273
330
  confidence?: number;
274
331
  risk?: RiskLevel;
332
+ /** Suggestion for how to fix the error */
333
+ suggestion?: string;
334
+ /** Whether to use E-format codes in output (default: true) */
335
+ useEFormat?: boolean;
275
336
  }
276
337
  /**
277
338
  * Build a standardized error response with enhanced taxonomy.
339
+ * Supports both E-format (E1001) and legacy format (INVALID_INPUT) error codes.
340
+ *
341
+ * @param options Error response options
342
+ * @returns Standardized error envelope
278
343
  */
279
344
  export declare function makeErrorResponse(options: MakeErrorResponseOptions): EnvelopeResponseV22<unknown>;
280
345
  export interface MakeSuccessResponseOptions {
@@ -304,13 +369,15 @@ export interface RunOptions {
304
369
  }
305
370
  export declare function runModule(module: CognitiveModule, provider: Provider, options?: RunOptions): Promise<ModuleResult>;
306
371
  /** Event types emitted during streaming execution */
307
- export type StreamEventType = 'start' | 'chunk' | 'meta' | 'complete' | 'error';
372
+ export type StreamEventType = 'start' | 'delta' | 'meta' | 'end' | 'error';
308
373
  /** Event emitted during streaming execution */
309
374
  export interface StreamEvent {
310
375
  type: StreamEventType;
376
+ version: string;
311
377
  timestamp_ms: number;
312
- module_name: string;
313
- chunk?: string;
378
+ module: string;
379
+ provider?: string;
380
+ delta?: string;
314
381
  meta?: EnvelopeMeta;
315
382
  result?: EnvelopeResponseV22<unknown>;
316
383
  error?: {
@@ -333,9 +400,9 @@ export interface StreamOptions {
333
400
  *
334
401
  * Yields StreamEvent objects as the module executes:
335
402
  * - type="start": Module execution started
336
- * - type="chunk": Incremental data chunk (if LLM supports streaming)
403
+ * - type="delta": Incremental output delta (provider streaming chunk)
337
404
  * - type="meta": Meta information available early
338
- * - type="complete": Final complete result
405
+ * - type="end": Final result envelope (always emitted)
339
406
  * - type="error": Error occurred
340
407
  *
341
408
  * @example