cognitive-modules-cli 2.2.0 → 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.
Files changed (94) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +35 -29
  4. package/dist/cli.js +572 -28
  5. package/dist/commands/add.d.ts +33 -14
  6. package/dist/commands/add.js +222 -13
  7. package/dist/commands/compose.d.ts +31 -0
  8. package/dist/commands/compose.js +185 -0
  9. package/dist/commands/index.d.ts +5 -0
  10. package/dist/commands/index.js +5 -0
  11. package/dist/commands/init.js +23 -1
  12. package/dist/commands/migrate.d.ts +30 -0
  13. package/dist/commands/migrate.js +650 -0
  14. package/dist/commands/pipe.d.ts +1 -0
  15. package/dist/commands/pipe.js +31 -11
  16. package/dist/commands/remove.js +33 -2
  17. package/dist/commands/run.d.ts +1 -0
  18. package/dist/commands/run.js +37 -27
  19. package/dist/commands/search.d.ts +28 -0
  20. package/dist/commands/search.js +143 -0
  21. package/dist/commands/test.d.ts +65 -0
  22. package/dist/commands/test.js +454 -0
  23. package/dist/commands/update.d.ts +1 -0
  24. package/dist/commands/update.js +106 -14
  25. package/dist/commands/validate.d.ts +36 -0
  26. package/dist/commands/validate.js +97 -0
  27. package/dist/errors/index.d.ts +218 -0
  28. package/dist/errors/index.js +412 -0
  29. package/dist/index.d.ts +2 -2
  30. package/dist/index.js +5 -1
  31. package/dist/mcp/server.js +84 -79
  32. package/dist/modules/composition.d.ts +251 -0
  33. package/dist/modules/composition.js +1330 -0
  34. package/dist/modules/index.d.ts +2 -0
  35. package/dist/modules/index.js +2 -0
  36. package/dist/modules/loader.d.ts +22 -2
  37. package/dist/modules/loader.js +171 -6
  38. package/dist/modules/runner.d.ts +422 -1
  39. package/dist/modules/runner.js +1472 -71
  40. package/dist/modules/subagent.d.ts +6 -1
  41. package/dist/modules/subagent.js +20 -13
  42. package/dist/modules/validator.d.ts +28 -0
  43. package/dist/modules/validator.js +637 -0
  44. package/dist/providers/anthropic.d.ts +15 -0
  45. package/dist/providers/anthropic.js +147 -5
  46. package/dist/providers/base.d.ts +11 -0
  47. package/dist/providers/base.js +18 -0
  48. package/dist/providers/gemini.d.ts +15 -0
  49. package/dist/providers/gemini.js +122 -5
  50. package/dist/providers/ollama.d.ts +15 -0
  51. package/dist/providers/ollama.js +111 -3
  52. package/dist/providers/openai.d.ts +11 -0
  53. package/dist/providers/openai.js +133 -0
  54. package/dist/registry/client.d.ts +204 -0
  55. package/dist/registry/client.js +356 -0
  56. package/dist/registry/index.d.ts +4 -0
  57. package/dist/registry/index.js +4 -0
  58. package/dist/server/http.js +173 -42
  59. package/dist/types.d.ts +123 -8
  60. package/dist/types.js +4 -1
  61. package/dist/version.d.ts +1 -0
  62. package/dist/version.js +4 -0
  63. package/package.json +32 -7
  64. package/src/cli.ts +0 -410
  65. package/src/commands/add.ts +0 -315
  66. package/src/commands/index.ts +0 -12
  67. package/src/commands/init.ts +0 -94
  68. package/src/commands/list.ts +0 -33
  69. package/src/commands/pipe.ts +0 -76
  70. package/src/commands/remove.ts +0 -57
  71. package/src/commands/run.ts +0 -80
  72. package/src/commands/update.ts +0 -130
  73. package/src/commands/versions.ts +0 -79
  74. package/src/index.ts +0 -55
  75. package/src/mcp/index.ts +0 -5
  76. package/src/mcp/server.ts +0 -403
  77. package/src/modules/index.ts +0 -7
  78. package/src/modules/loader.ts +0 -318
  79. package/src/modules/runner.ts +0 -495
  80. package/src/modules/subagent.ts +0 -275
  81. package/src/providers/anthropic.ts +0 -89
  82. package/src/providers/base.ts +0 -29
  83. package/src/providers/deepseek.ts +0 -83
  84. package/src/providers/gemini.ts +0 -117
  85. package/src/providers/index.ts +0 -78
  86. package/src/providers/minimax.ts +0 -81
  87. package/src/providers/moonshot.ts +0 -82
  88. package/src/providers/ollama.ts +0 -83
  89. package/src/providers/openai.ts +0 -84
  90. package/src/providers/qwen.ts +0 -82
  91. package/src/server/http.ts +0 -316
  92. package/src/server/index.ts +0 -6
  93. package/src/types.ts +0 -495
  94. package/tsconfig.json +0 -17
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Registry Module - Re-export all registry functionality
3
+ */
4
+ export * from './client.js';
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Registry Module - Re-export all registry functionality
3
+ */
4
+ export * from './client.js';
@@ -15,22 +15,62 @@ import { URL } from 'node:url';
15
15
  import { findModule, listModules, getDefaultSearchPaths } from '../modules/loader.js';
16
16
  import { runModule } from '../modules/runner.js';
17
17
  import { getProvider } from '../providers/index.js';
18
+ import { VERSION } from '../version.js';
19
+ import { ErrorCodes, makeErrorEnvelope, makeHttpError } from '../errors/index.js';
20
+ // Supported protocol versions
21
+ const SUPPORTED_VERSIONS = ['2.2', '2.1'];
22
+ const DEFAULT_VERSION = '2.2';
23
+ /**
24
+ * Get requested protocol version from request
25
+ * Priority: body.version > X-Cognitive-Version header > query param > default
26
+ */
27
+ function getRequestedVersion(req, url, bodyVersion) {
28
+ // Body version takes priority
29
+ if (bodyVersion && SUPPORTED_VERSIONS.includes(bodyVersion)) {
30
+ return bodyVersion;
31
+ }
32
+ // Check header
33
+ const headerVersion = req.headers['x-cognitive-version'];
34
+ if (headerVersion && SUPPORTED_VERSIONS.includes(headerVersion)) {
35
+ return headerVersion;
36
+ }
37
+ // Check query param
38
+ const queryVersion = url.searchParams.get('version');
39
+ if (queryVersion && SUPPORTED_VERSIONS.includes(queryVersion)) {
40
+ return queryVersion;
41
+ }
42
+ return DEFAULT_VERSION;
43
+ }
18
44
  // =============================================================================
19
45
  // Helpers
20
46
  // =============================================================================
21
- function jsonResponse(res, status, data) {
47
+ function jsonResponse(res, status, data, protocolVersion = DEFAULT_VERSION) {
22
48
  res.writeHead(status, {
23
49
  'Content-Type': 'application/json',
24
50
  'Access-Control-Allow-Origin': '*',
25
51
  'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
26
- 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
52
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Cognitive-Version',
53
+ 'X-Cognitive-Version': protocolVersion,
27
54
  });
28
55
  res.end(JSON.stringify(data, null, 2));
29
56
  }
30
- function parseBody(req) {
57
+ const MAX_BODY_BYTES = 1024 * 1024; // 1MB
58
+ function parseBody(req, maxBytes = MAX_BODY_BYTES) {
31
59
  return new Promise((resolve, reject) => {
32
60
  let body = '';
33
- req.on('data', (chunk) => (body += chunk));
61
+ let received = 0;
62
+ req.on('data', (chunk) => {
63
+ const chunkSize = typeof chunk === 'string' ? Buffer.byteLength(chunk) : chunk.length;
64
+ received += chunkSize;
65
+ if (received > maxBytes) {
66
+ const err = new Error('Payload too large');
67
+ err.code = 'PAYLOAD_TOO_LARGE';
68
+ req.destroy(err);
69
+ reject(err);
70
+ return;
71
+ }
72
+ body += chunk;
73
+ });
34
74
  req.on('end', () => resolve(body));
35
75
  req.on('error', reject);
36
76
  });
@@ -51,7 +91,16 @@ function verifyApiKey(req) {
51
91
  async function handleRoot(res) {
52
92
  jsonResponse(res, 200, {
53
93
  name: 'Cognitive Modules API',
54
- version: '1.3.0',
94
+ version: VERSION,
95
+ protocol: {
96
+ version: DEFAULT_VERSION,
97
+ supported: SUPPORTED_VERSIONS,
98
+ negotiation: {
99
+ header: 'X-Cognitive-Version',
100
+ query: '?version=2.2',
101
+ body: 'version field in request body',
102
+ },
103
+ },
55
104
  docs: '/docs',
56
105
  endpoints: {
57
106
  run: 'POST /run',
@@ -72,7 +121,7 @@ async function handleHealth(res) {
72
121
  };
73
122
  jsonResponse(res, 200, {
74
123
  status: 'healthy',
75
- version: '1.3.0',
124
+ version: VERSION,
76
125
  providers,
77
126
  });
78
127
  }
@@ -95,7 +144,12 @@ async function handleModules(res, searchPaths) {
95
144
  async function handleModuleInfo(res, moduleName, searchPaths) {
96
145
  const moduleData = await findModule(moduleName, searchPaths);
97
146
  if (!moduleData) {
98
- jsonResponse(res, 404, { error: `Module '${moduleName}' not found` });
147
+ const envelope = makeErrorEnvelope({
148
+ code: ErrorCodes.MODULE_NOT_FOUND,
149
+ message: `Module '${moduleName}' not found`,
150
+ suggestion: 'Use GET /modules to list available modules',
151
+ });
152
+ jsonResponse(res, 404, envelope);
99
153
  return;
100
154
  }
101
155
  jsonResponse(res, 200, {
@@ -110,12 +164,28 @@ async function handleModuleInfo(res, moduleName, searchPaths) {
110
164
  outputSchema: moduleData.outputSchema,
111
165
  });
112
166
  }
113
- async function handleRun(req, res, searchPaths) {
167
+ async function handleRun(req, res, searchPaths, url) {
168
+ // Version will be determined after parsing body
169
+ let protocolVersion = DEFAULT_VERSION;
170
+ // Helper to build error envelope using unified error factory
171
+ const buildHttpError = (code, message, options = {}) => {
172
+ const moduleName = options.moduleName ?? request?.module ?? 'unknown';
173
+ const providerName = options.providerName ?? request?.provider ?? 'unknown';
174
+ const [status, envelope] = makeHttpError({
175
+ code,
176
+ message,
177
+ version: protocolVersion,
178
+ suggestion: options.suggestion,
179
+ recoverable: options.recoverable,
180
+ retry_after_ms: options.retry_after_ms,
181
+ module: moduleName,
182
+ provider: providerName,
183
+ });
184
+ return [status, envelope];
185
+ };
114
186
  // Verify API key
115
187
  if (!verifyApiKey(req)) {
116
- jsonResponse(res, 401, {
117
- error: 'Missing or invalid API Key. Use header: Authorization: Bearer <your-api-key>',
118
- });
188
+ jsonResponse(res, 401, buildHttpError(ErrorCodes.PERMISSION_DENIED, 'Missing or invalid API Key', { suggestion: 'Use header: Authorization: Bearer <your-api-key>' }), protocolVersion);
119
189
  return;
120
190
  }
121
191
  // Parse request body
@@ -124,52 +194,102 @@ async function handleRun(req, res, searchPaths) {
124
194
  const body = await parseBody(req);
125
195
  request = JSON.parse(body);
126
196
  }
127
- catch {
128
- jsonResponse(res, 400, { error: 'Invalid JSON body' });
197
+ catch (e) {
198
+ const err = e;
199
+ if (err?.code === 'PAYLOAD_TOO_LARGE') {
200
+ const [status, body] = buildHttpError(ErrorCodes.INPUT_TOO_LARGE, 'Payload too large', { suggestion: 'Reduce input size to under 1MB' });
201
+ jsonResponse(res, status, body, protocolVersion);
202
+ return;
203
+ }
204
+ const [status, body] = buildHttpError(ErrorCodes.PARSE_ERROR, 'Invalid JSON body', { suggestion: 'Ensure request body is valid JSON' });
205
+ jsonResponse(res, status, body, protocolVersion);
129
206
  return;
130
207
  }
208
+ if (!request || typeof request !== 'object') {
209
+ const [status, body] = buildHttpError(ErrorCodes.INVALID_INPUT, 'Invalid request body', { suggestion: 'Ensure request body is a JSON object' });
210
+ jsonResponse(res, status, body, protocolVersion);
211
+ return;
212
+ }
213
+ const reqBody = request;
214
+ // Determine protocol version (body > header > query > default)
215
+ protocolVersion = getRequestedVersion(req, url, reqBody.version);
131
216
  // Validate request
132
- if (!request.module || !request.args) {
133
- jsonResponse(res, 400, { error: 'Missing required fields: module, args' });
217
+ if (!reqBody.module || !reqBody.args) {
218
+ const [status, body] = buildHttpError(ErrorCodes.MISSING_REQUIRED_FIELD, 'Missing required fields: module, args', {
219
+ moduleName: reqBody?.module ?? 'unknown',
220
+ suggestion: 'Provide both "module" and "args" fields in request body'
221
+ });
222
+ jsonResponse(res, status, body, protocolVersion);
134
223
  return;
135
224
  }
136
225
  // Find module
137
- const moduleData = await findModule(request.module, searchPaths);
226
+ const moduleData = await findModule(reqBody.module, searchPaths);
138
227
  if (!moduleData) {
139
- jsonResponse(res, 404, { error: `Module '${request.module}' not found` });
228
+ const [status, body] = buildHttpError(ErrorCodes.MODULE_NOT_FOUND, `Module '${reqBody.module}' not found`, {
229
+ moduleName: reqBody.module,
230
+ suggestion: 'Use GET /modules to list available modules'
231
+ });
232
+ jsonResponse(res, status, body, protocolVersion);
140
233
  return;
141
234
  }
142
235
  try {
143
236
  // Create provider
144
- const provider = getProvider(request.provider, request.model);
145
- // Run module
237
+ const provider = getProvider(reqBody.provider, reqBody.model);
238
+ const providerName = provider.name;
239
+ // Run module (always use v2.2 format internally)
146
240
  const result = await runModule(moduleData, provider, {
147
- input: { query: request.args, code: request.args },
241
+ args: reqBody.args,
148
242
  useV22: true,
149
243
  });
150
- const response = {
151
- ok: result.ok,
152
- module: request.module,
153
- provider: request.provider || process.env.LLM_PROVIDER || 'openai',
154
- };
155
- if (result.ok) {
156
- if ('meta' in result)
157
- response.meta = result.meta;
158
- if ('data' in result)
159
- response.data = result.data;
244
+ // Build response envelope with requested protocol version
245
+ if (result.ok && 'data' in result) {
246
+ const v22Result = result;
247
+ const response = {
248
+ ok: true,
249
+ version: protocolVersion,
250
+ meta: v22Result.meta ?? {
251
+ confidence: 0.5,
252
+ risk: 'medium',
253
+ explain: 'No meta provided',
254
+ },
255
+ data: v22Result.data,
256
+ module: reqBody.module,
257
+ provider: providerName,
258
+ };
259
+ jsonResponse(res, 200, response, protocolVersion);
160
260
  }
161
261
  else {
162
- if ('error' in result)
163
- response.error = result.error?.message;
262
+ // Error response - must include meta and full error object
263
+ const errorResult = result;
264
+ const response = {
265
+ ok: false,
266
+ version: protocolVersion,
267
+ meta: errorResult.meta ?? {
268
+ confidence: 0.0,
269
+ risk: 'high',
270
+ explain: errorResult.error?.message ?? 'An error occurred',
271
+ },
272
+ error: errorResult.error ?? {
273
+ code: ErrorCodes.INTERNAL_ERROR,
274
+ message: 'Unknown error',
275
+ recoverable: false,
276
+ },
277
+ partial_data: errorResult.partial_data,
278
+ module: reqBody.module,
279
+ provider: providerName,
280
+ };
281
+ jsonResponse(res, 200, response, protocolVersion);
164
282
  }
165
- jsonResponse(res, 200, response);
166
283
  }
167
284
  catch (error) {
168
- jsonResponse(res, 500, {
169
- ok: false,
170
- error: error instanceof Error ? error.message : String(error),
171
- module: request.module,
285
+ // Infrastructure error - still return envelope
286
+ const errorMessage = error instanceof Error ? error.message : String(error);
287
+ const [status, response] = buildHttpError(ErrorCodes.INTERNAL_ERROR, errorMessage, {
288
+ moduleName: reqBody?.module,
289
+ providerName: reqBody?.provider,
290
+ recoverable: false,
172
291
  });
292
+ jsonResponse(res, status, response, protocolVersion);
173
293
  }
174
294
  }
175
295
  export function createServer(options = {}) {
@@ -184,7 +304,8 @@ export function createServer(options = {}) {
184
304
  res.writeHead(204, {
185
305
  'Access-Control-Allow-Origin': '*',
186
306
  'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
187
- 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
307
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Cognitive-Version',
308
+ 'Access-Control-Expose-Headers': 'X-Cognitive-Version',
188
309
  });
189
310
  res.end();
190
311
  return;
@@ -205,17 +326,27 @@ export function createServer(options = {}) {
205
326
  await handleModuleInfo(res, moduleName, searchPaths);
206
327
  }
207
328
  else if (path === '/run' && method === 'POST') {
208
- await handleRun(req, res, searchPaths);
329
+ await handleRun(req, res, searchPaths, url);
209
330
  }
210
331
  else {
211
- jsonResponse(res, 404, { error: 'Not found' });
332
+ const envelope = makeErrorEnvelope({
333
+ code: ErrorCodes.ENDPOINT_NOT_FOUND,
334
+ message: `Endpoint '${path}' not found`,
335
+ suggestion: 'Use GET / to see available endpoints',
336
+ risk: 'low',
337
+ });
338
+ jsonResponse(res, 404, envelope);
212
339
  }
213
340
  }
214
341
  catch (error) {
215
342
  console.error('Server error:', error);
216
- jsonResponse(res, 500, {
217
- error: error instanceof Error ? error.message : 'Internal server error',
343
+ const errorMessage = error instanceof Error ? error.message : 'Internal server error';
344
+ const envelope = makeErrorEnvelope({
345
+ code: ErrorCodes.INTERNAL_ERROR,
346
+ message: errorMessage,
347
+ recoverable: false,
218
348
  });
349
+ jsonResponse(res, 500, envelope);
219
350
  }
220
351
  });
221
352
  return server;
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[];
@@ -35,6 +46,77 @@ export type RiskLevel = 'none' | 'low' | 'medium' | 'high';
35
46
  export type EnumStrategy = 'strict' | 'extensible';
36
47
  /** Risk aggregation rule */
37
48
  export type RiskRule = 'max_changes_risk' | 'max_issues_risk' | 'explicit';
49
+ /** Composition pattern types */
50
+ export type CompositionPattern = 'sequential' | 'parallel' | 'conditional' | 'iterative';
51
+ /** Aggregation strategy for combining multiple outputs */
52
+ export type AggregationStrategy = 'merge' | 'array' | 'first' | 'custom';
53
+ /** Semver-like version matching pattern */
54
+ export type VersionPattern = string;
55
+ /** Dependency declaration for composition.requires */
56
+ export interface DependencyDeclaration {
57
+ /** Module name */
58
+ name: string;
59
+ /** Semver version pattern */
60
+ version?: VersionPattern;
61
+ /** Whether dependency is optional */
62
+ optional?: boolean;
63
+ /** Fallback module if unavailable */
64
+ fallback?: string | null;
65
+ /** Per-module timeout (ms) */
66
+ timeout_ms?: number;
67
+ }
68
+ /** Dataflow mapping expression */
69
+ export interface DataflowMapping {
70
+ [key: string]: string;
71
+ }
72
+ /** Dataflow step configuration */
73
+ export interface DataflowStep {
74
+ /** Source of data: 'input' or 'module-name.output' */
75
+ from: string | string[];
76
+ /** Destination: module name or 'output' */
77
+ to: string | string[];
78
+ /** Field mapping expressions */
79
+ mapping?: DataflowMapping;
80
+ /** Condition for execution */
81
+ condition?: string;
82
+ /** Aggregation strategy when from is an array */
83
+ aggregate?: AggregationStrategy;
84
+ /** Custom aggregation function name */
85
+ aggregator?: string;
86
+ }
87
+ /** Conditional routing rule */
88
+ export interface RoutingRule {
89
+ /** Condition expression */
90
+ condition: string;
91
+ /** Next module to execute (null means use current result) */
92
+ next: string | null;
93
+ }
94
+ /** Iteration configuration */
95
+ export interface IterationConfig {
96
+ /** Maximum iterations */
97
+ max_iterations?: number;
98
+ /** Condition to continue iterating */
99
+ continue_condition?: string;
100
+ /** Condition to stop iterating */
101
+ stop_condition?: string;
102
+ }
103
+ /** Full composition configuration (from module.yaml) */
104
+ export interface CompositionConfig {
105
+ /** Composition pattern */
106
+ pattern: CompositionPattern;
107
+ /** Required dependencies */
108
+ requires?: DependencyDeclaration[];
109
+ /** Dataflow configuration */
110
+ dataflow?: DataflowStep[];
111
+ /** Conditional routing rules */
112
+ routing?: RoutingRule[];
113
+ /** Maximum composition depth */
114
+ max_depth?: number;
115
+ /** Total timeout for composition (ms) */
116
+ timeout_ms?: number;
117
+ /** Iteration configuration */
118
+ iteration?: IterationConfig;
119
+ }
38
120
  export interface CognitiveModule {
39
121
  name: string;
40
122
  version: string;
@@ -52,6 +134,7 @@ export interface CognitiveModule {
52
134
  enums?: EnumConfig;
53
135
  compat?: CompatConfig;
54
136
  metaConfig?: MetaConfig;
137
+ composition?: CompositionConfig;
55
138
  context?: 'fork' | 'main';
56
139
  prompt: string;
57
140
  inputSchema?: object;
@@ -148,20 +231,39 @@ export interface EnvelopeMeta {
148
231
  /** Execution latency in milliseconds */
149
232
  latency_ms?: number;
150
233
  }
234
+ /**
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.
239
+ */
240
+ export interface EnvelopeError {
241
+ /** Error code (E-format like "E4006" or legacy like "MODULE_NOT_FOUND") */
242
+ code: string;
243
+ /** Human-readable error message */
244
+ message: string;
245
+ /** Whether the error can be retried */
246
+ recoverable?: boolean;
247
+ /** Suggested action to fix the error */
248
+ suggestion?: string;
249
+ /** Suggested wait time before retry (in milliseconds) */
250
+ retry_after_ms?: number;
251
+ /** Additional error context */
252
+ details?: Record<string, unknown>;
253
+ }
151
254
  /** Success response in v2.2 envelope format */
152
255
  export interface EnvelopeSuccessV22<T = unknown> {
153
256
  ok: true;
257
+ version?: string;
154
258
  meta: EnvelopeMeta;
155
259
  data: T;
156
260
  }
157
261
  /** Error response in v2.2 envelope format */
158
262
  export interface EnvelopeErrorV22 {
159
263
  ok: false;
264
+ version?: string;
160
265
  meta: EnvelopeMeta;
161
- error: {
162
- code: string;
163
- message: string;
164
- };
266
+ error: EnvelopeError;
165
267
  partial_data?: unknown;
166
268
  }
167
269
  /** v2.2 envelope response (union type) */
@@ -217,12 +319,10 @@ export interface ModuleResultData {
217
319
  /** v2.2 module result with meta and data separation */
218
320
  export interface ModuleResultV22 {
219
321
  ok: boolean;
322
+ version?: string;
220
323
  meta: EnvelopeMeta;
221
324
  data?: ModuleResultData;
222
- error?: {
223
- code: string;
224
- message: string;
225
- };
325
+ error?: EnvelopeError;
226
326
  partial_data?: unknown;
227
327
  raw?: string;
228
328
  }
@@ -253,11 +353,26 @@ export interface CommandContext {
253
353
  provider: Provider;
254
354
  verbose?: boolean;
255
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
+ */
256
362
  export interface CommandResult {
257
363
  success: boolean;
258
364
  data?: unknown;
259
365
  error?: string;
260
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
+ }
261
376
  export interface ModuleInput {
262
377
  code?: string;
263
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 level = riskLevels[item.risk ?? 'medium'];
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;
@@ -0,0 +1,4 @@
1
+ import { createRequire } from 'node:module';
2
+ const require = createRequire(import.meta.url);
3
+ const pkg = require('../package.json');
4
+ export const VERSION = pkg.version ?? '0.0.0';
package/package.json CHANGED
@@ -1,18 +1,32 @@
1
1
  {
2
2
  "name": "cognitive-modules-cli",
3
- "version": "2.2.0",
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
- "build": "tsc",
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
- "prepublishOnly": "npm run build"
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,18 +39,28 @@
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/ziel-io/cognitive-modules.git"
50
+ "url": "https://github.com/Cognary/cognitive.git"
31
51
  },
32
- "homepage": "https://ziel-io.github.io/cognitive-modules/",
52
+ "homepage": "https://cognary.github.io/cognitive/",
33
53
  "bugs": {
34
- "url": "https://github.com/ziel-io/cognitive-modules/issues"
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"
38
61
  },
39
62
  "dependencies": {
63
+ "ajv": "^8.12.0",
40
64
  "js-yaml": "^4.1.1"
41
65
  },
42
66
  "optionalDependencies": {
@@ -46,6 +70,7 @@
46
70
  "@types/js-yaml": "^4.0.9",
47
71
  "@types/node": "^22.0.0",
48
72
  "tsx": "^4.21.0",
49
- "typescript": "^5.9.3"
73
+ "typescript": "^5.9.3",
74
+ "vitest": "^2.1.0"
50
75
  }
51
76
  }