cognitive-modules-cli 1.2.0 → 1.4.0
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/README.md +21 -13
- package/dist/cli.js +35 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +7 -1
- package/dist/mcp/index.d.ts +4 -0
- package/dist/mcp/index.js +4 -0
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.js +344 -0
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.js +1 -0
- package/dist/modules/loader.js +7 -2
- package/dist/modules/runner.d.ts +44 -2
- package/dist/modules/runner.js +611 -4
- package/dist/modules/subagent.d.ts +65 -0
- package/dist/modules/subagent.js +185 -0
- package/dist/providers/base.d.ts +45 -1
- package/dist/providers/base.js +67 -0
- package/dist/providers/openai.d.ts +27 -3
- package/dist/providers/openai.js +175 -3
- package/dist/server/http.d.ts +20 -0
- package/dist/server/http.js +243 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.js +4 -0
- package/dist/types.d.ts +208 -1
- package/dist/types.js +82 -1
- package/package.json +4 -1
- package/src/cli.ts +36 -1
- package/src/index.ts +11 -0
- package/src/mcp/index.ts +5 -0
- package/src/mcp/server.ts +403 -0
- package/src/modules/index.ts +1 -0
- package/src/modules/loader.ts +8 -2
- package/src/modules/runner.ts +803 -5
- package/src/modules/subagent.ts +275 -0
- package/src/providers/base.ts +86 -1
- package/src/providers/openai.ts +226 -4
- package/src/server/http.ts +316 -0
- package/src/server/index.ts +6 -0
- package/src/types.ts +319 -1
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cognitive Modules HTTP API Server
|
|
3
|
+
*
|
|
4
|
+
* Provides RESTful API interface for workflow platform integration.
|
|
5
|
+
*
|
|
6
|
+
* Start with:
|
|
7
|
+
* cog serve --port 8000
|
|
8
|
+
*
|
|
9
|
+
* Environment variables:
|
|
10
|
+
* COGNITIVE_API_KEY - API Key authentication (optional)
|
|
11
|
+
* OPENAI_API_KEY, ANTHROPIC_API_KEY, etc. - LLM provider keys
|
|
12
|
+
*/
|
|
13
|
+
import http from 'node:http';
|
|
14
|
+
import { URL } from 'node:url';
|
|
15
|
+
import { findModule, listModules, getDefaultSearchPaths } from '../modules/loader.js';
|
|
16
|
+
import { runModule } from '../modules/runner.js';
|
|
17
|
+
import { getProvider } from '../providers/index.js';
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// Helpers
|
|
20
|
+
// =============================================================================
|
|
21
|
+
function jsonResponse(res, status, data) {
|
|
22
|
+
res.writeHead(status, {
|
|
23
|
+
'Content-Type': 'application/json',
|
|
24
|
+
'Access-Control-Allow-Origin': '*',
|
|
25
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
26
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
27
|
+
});
|
|
28
|
+
res.end(JSON.stringify(data, null, 2));
|
|
29
|
+
}
|
|
30
|
+
function parseBody(req) {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
let body = '';
|
|
33
|
+
req.on('data', (chunk) => (body += chunk));
|
|
34
|
+
req.on('end', () => resolve(body));
|
|
35
|
+
req.on('error', reject);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function verifyApiKey(req) {
|
|
39
|
+
const expectedKey = process.env.COGNITIVE_API_KEY;
|
|
40
|
+
if (!expectedKey)
|
|
41
|
+
return true; // No auth required
|
|
42
|
+
const authHeader = req.headers.authorization;
|
|
43
|
+
if (!authHeader)
|
|
44
|
+
return false;
|
|
45
|
+
const token = authHeader.startsWith('Bearer ') ? authHeader.slice(7) : authHeader;
|
|
46
|
+
return token === expectedKey;
|
|
47
|
+
}
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// Request Handlers
|
|
50
|
+
// =============================================================================
|
|
51
|
+
async function handleRoot(res) {
|
|
52
|
+
jsonResponse(res, 200, {
|
|
53
|
+
name: 'Cognitive Modules API',
|
|
54
|
+
version: '1.3.0',
|
|
55
|
+
docs: '/docs',
|
|
56
|
+
endpoints: {
|
|
57
|
+
run: 'POST /run',
|
|
58
|
+
modules: 'GET /modules',
|
|
59
|
+
module_info: 'GET /modules/{name}',
|
|
60
|
+
health: 'GET /health',
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async function handleHealth(res) {
|
|
65
|
+
const providers = {
|
|
66
|
+
openai: Boolean(process.env.OPENAI_API_KEY),
|
|
67
|
+
anthropic: Boolean(process.env.ANTHROPIC_API_KEY),
|
|
68
|
+
minimax: Boolean(process.env.MINIMAX_API_KEY),
|
|
69
|
+
deepseek: Boolean(process.env.DEEPSEEK_API_KEY),
|
|
70
|
+
gemini: Boolean(process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY),
|
|
71
|
+
qwen: Boolean(process.env.QWEN_API_KEY || process.env.DASHSCOPE_API_KEY),
|
|
72
|
+
};
|
|
73
|
+
jsonResponse(res, 200, {
|
|
74
|
+
status: 'healthy',
|
|
75
|
+
version: '1.3.0',
|
|
76
|
+
providers,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async function handleModules(res, searchPaths) {
|
|
80
|
+
const modules = await listModules(searchPaths);
|
|
81
|
+
const moduleInfos = modules.map((m) => ({
|
|
82
|
+
name: m.name,
|
|
83
|
+
version: m.version,
|
|
84
|
+
description: m.responsibility,
|
|
85
|
+
format: m.format,
|
|
86
|
+
path: m.location,
|
|
87
|
+
responsibility: m.responsibility,
|
|
88
|
+
tier: m.tier,
|
|
89
|
+
}));
|
|
90
|
+
jsonResponse(res, 200, {
|
|
91
|
+
modules: moduleInfos,
|
|
92
|
+
count: moduleInfos.length,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
async function handleModuleInfo(res, moduleName, searchPaths) {
|
|
96
|
+
const moduleData = await findModule(moduleName, searchPaths);
|
|
97
|
+
if (!moduleData) {
|
|
98
|
+
jsonResponse(res, 404, { error: `Module '${moduleName}' not found` });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
jsonResponse(res, 200, {
|
|
102
|
+
name: moduleData.name,
|
|
103
|
+
version: moduleData.version,
|
|
104
|
+
description: moduleData.responsibility,
|
|
105
|
+
format: moduleData.format,
|
|
106
|
+
path: moduleData.location,
|
|
107
|
+
responsibility: moduleData.responsibility,
|
|
108
|
+
tier: moduleData.tier,
|
|
109
|
+
inputSchema: moduleData.inputSchema,
|
|
110
|
+
outputSchema: moduleData.outputSchema,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
async function handleRun(req, res, searchPaths) {
|
|
114
|
+
// Verify API key
|
|
115
|
+
if (!verifyApiKey(req)) {
|
|
116
|
+
jsonResponse(res, 401, {
|
|
117
|
+
error: 'Missing or invalid API Key. Use header: Authorization: Bearer <your-api-key>',
|
|
118
|
+
});
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
// Parse request body
|
|
122
|
+
let request;
|
|
123
|
+
try {
|
|
124
|
+
const body = await parseBody(req);
|
|
125
|
+
request = JSON.parse(body);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
jsonResponse(res, 400, { error: 'Invalid JSON body' });
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
// Validate request
|
|
132
|
+
if (!request.module || !request.args) {
|
|
133
|
+
jsonResponse(res, 400, { error: 'Missing required fields: module, args' });
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Find module
|
|
137
|
+
const moduleData = await findModule(request.module, searchPaths);
|
|
138
|
+
if (!moduleData) {
|
|
139
|
+
jsonResponse(res, 404, { error: `Module '${request.module}' not found` });
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
// Create provider
|
|
144
|
+
const provider = getProvider(request.provider, request.model);
|
|
145
|
+
// Run module
|
|
146
|
+
const result = await runModule(moduleData, provider, {
|
|
147
|
+
input: { query: request.args, code: request.args },
|
|
148
|
+
useV22: true,
|
|
149
|
+
});
|
|
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;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
if ('error' in result)
|
|
163
|
+
response.error = result.error?.message;
|
|
164
|
+
}
|
|
165
|
+
jsonResponse(res, 200, response);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
jsonResponse(res, 500, {
|
|
169
|
+
ok: false,
|
|
170
|
+
error: error instanceof Error ? error.message : String(error),
|
|
171
|
+
module: request.module,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
export function createServer(options = {}) {
|
|
176
|
+
const { cwd = process.cwd() } = options;
|
|
177
|
+
const searchPaths = getDefaultSearchPaths(cwd);
|
|
178
|
+
const server = http.createServer(async (req, res) => {
|
|
179
|
+
const url = new URL(req.url || '/', `http://${req.headers.host}`);
|
|
180
|
+
const path = url.pathname;
|
|
181
|
+
const method = req.method?.toUpperCase();
|
|
182
|
+
// Handle CORS preflight
|
|
183
|
+
if (method === 'OPTIONS') {
|
|
184
|
+
res.writeHead(204, {
|
|
185
|
+
'Access-Control-Allow-Origin': '*',
|
|
186
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
187
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
188
|
+
});
|
|
189
|
+
res.end();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
// Route requests
|
|
194
|
+
if (path === '/' && method === 'GET') {
|
|
195
|
+
await handleRoot(res);
|
|
196
|
+
}
|
|
197
|
+
else if (path === '/health' && method === 'GET') {
|
|
198
|
+
await handleHealth(res);
|
|
199
|
+
}
|
|
200
|
+
else if (path === '/modules' && method === 'GET') {
|
|
201
|
+
await handleModules(res, searchPaths);
|
|
202
|
+
}
|
|
203
|
+
else if (path.startsWith('/modules/') && method === 'GET') {
|
|
204
|
+
const moduleName = path.slice('/modules/'.length);
|
|
205
|
+
await handleModuleInfo(res, moduleName, searchPaths);
|
|
206
|
+
}
|
|
207
|
+
else if (path === '/run' && method === 'POST') {
|
|
208
|
+
await handleRun(req, res, searchPaths);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
jsonResponse(res, 404, { error: 'Not found' });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
console.error('Server error:', error);
|
|
216
|
+
jsonResponse(res, 500, {
|
|
217
|
+
error: error instanceof Error ? error.message : 'Internal server error',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
return server;
|
|
222
|
+
}
|
|
223
|
+
export async function serve(options = {}) {
|
|
224
|
+
const { host = '0.0.0.0', port = 8000 } = options;
|
|
225
|
+
const server = createServer(options);
|
|
226
|
+
return new Promise((resolve, reject) => {
|
|
227
|
+
server.on('error', reject);
|
|
228
|
+
server.listen(port, host, () => {
|
|
229
|
+
console.log(`Cognitive Modules HTTP Server running at http://${host}:${port}`);
|
|
230
|
+
console.log('Endpoints:');
|
|
231
|
+
console.log(' GET / - API info');
|
|
232
|
+
console.log(' GET /health - Health check');
|
|
233
|
+
console.log(' GET /modules - List modules');
|
|
234
|
+
console.log(' GET /modules/:name - Module info');
|
|
235
|
+
console.log(' POST /run - Run module');
|
|
236
|
+
resolve();
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
// Allow running directly
|
|
241
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
242
|
+
serve().catch(console.error);
|
|
243
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cognitive Runtime - Core Types
|
|
3
|
-
* Version 2.
|
|
3
|
+
* Version 2.5 - With streaming response and multimodal support
|
|
4
4
|
*/
|
|
5
5
|
export interface Provider {
|
|
6
6
|
name: string;
|
|
@@ -282,3 +282,210 @@ export declare function extractMeta<T>(response: EnvelopeResponse<T>, riskRule?:
|
|
|
282
282
|
export declare function aggregateRisk(data: Record<string, unknown>, riskRule?: RiskRule): RiskLevel;
|
|
283
283
|
/** Check if result should be escalated to human review */
|
|
284
284
|
export declare function shouldEscalate<T>(response: EnvelopeResponse<T>, confidenceThreshold?: number): boolean;
|
|
285
|
+
/** Response mode configuration */
|
|
286
|
+
export type ResponseMode = 'sync' | 'streaming' | 'both';
|
|
287
|
+
/** Chunk type for streaming */
|
|
288
|
+
export type ChunkType = 'delta' | 'snapshot';
|
|
289
|
+
/** Response configuration in module.yaml */
|
|
290
|
+
export interface ResponseConfig {
|
|
291
|
+
mode: ResponseMode;
|
|
292
|
+
chunk_type?: ChunkType;
|
|
293
|
+
buffer_size?: number;
|
|
294
|
+
heartbeat_interval_ms?: number;
|
|
295
|
+
max_duration_ms?: number;
|
|
296
|
+
}
|
|
297
|
+
/** Meta chunk - initial streaming response */
|
|
298
|
+
export interface MetaChunk {
|
|
299
|
+
ok: true;
|
|
300
|
+
streaming: true;
|
|
301
|
+
session_id: string;
|
|
302
|
+
meta: Partial<EnvelopeMeta>;
|
|
303
|
+
}
|
|
304
|
+
/** Delta chunk - incremental content */
|
|
305
|
+
export interface DeltaChunk {
|
|
306
|
+
chunk: {
|
|
307
|
+
seq: number;
|
|
308
|
+
type: 'delta';
|
|
309
|
+
field?: string;
|
|
310
|
+
delta: string;
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
/** Snapshot chunk - full state replacement */
|
|
314
|
+
export interface SnapshotChunk {
|
|
315
|
+
chunk: {
|
|
316
|
+
seq: number;
|
|
317
|
+
type: 'snapshot';
|
|
318
|
+
field?: string;
|
|
319
|
+
data: unknown;
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
/** Progress chunk - progress update */
|
|
323
|
+
export interface ProgressChunk {
|
|
324
|
+
progress: {
|
|
325
|
+
percent: number;
|
|
326
|
+
stage?: string;
|
|
327
|
+
message?: string;
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
/** Final chunk - completion signal */
|
|
331
|
+
export interface FinalChunk {
|
|
332
|
+
final: true;
|
|
333
|
+
meta: EnvelopeMeta;
|
|
334
|
+
data: ModuleResultData;
|
|
335
|
+
usage?: {
|
|
336
|
+
input_tokens: number;
|
|
337
|
+
output_tokens: number;
|
|
338
|
+
total_tokens: number;
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/** Error chunk during streaming */
|
|
342
|
+
export interface ErrorChunk {
|
|
343
|
+
ok: false;
|
|
344
|
+
streaming: true;
|
|
345
|
+
session_id?: string;
|
|
346
|
+
error: {
|
|
347
|
+
code: string;
|
|
348
|
+
message: string;
|
|
349
|
+
recoverable?: boolean;
|
|
350
|
+
};
|
|
351
|
+
partial_data?: unknown;
|
|
352
|
+
}
|
|
353
|
+
/** Union of all streaming chunk types */
|
|
354
|
+
export type StreamingChunk = MetaChunk | DeltaChunk | SnapshotChunk | ProgressChunk | FinalChunk | ErrorChunk;
|
|
355
|
+
/** Streaming session state */
|
|
356
|
+
export interface StreamingSession {
|
|
357
|
+
session_id: string;
|
|
358
|
+
module_name: string;
|
|
359
|
+
started_at: number;
|
|
360
|
+
chunks_sent: number;
|
|
361
|
+
accumulated_data: Record<string, unknown>;
|
|
362
|
+
accumulated_text: Record<string, string>;
|
|
363
|
+
}
|
|
364
|
+
/** Supported modality types */
|
|
365
|
+
export type ModalityType = 'text' | 'image' | 'audio' | 'video' | 'document';
|
|
366
|
+
/** Modalities configuration in module.yaml */
|
|
367
|
+
export interface ModalitiesConfig {
|
|
368
|
+
input: ModalityType[];
|
|
369
|
+
output: ModalityType[];
|
|
370
|
+
constraints?: MediaConstraints;
|
|
371
|
+
}
|
|
372
|
+
/** Media size/duration constraints */
|
|
373
|
+
export interface MediaConstraints {
|
|
374
|
+
max_image_size_mb?: number;
|
|
375
|
+
max_audio_size_mb?: number;
|
|
376
|
+
max_video_size_mb?: number;
|
|
377
|
+
max_audio_duration_s?: number;
|
|
378
|
+
max_video_duration_s?: number;
|
|
379
|
+
allowed_image_types?: string[];
|
|
380
|
+
allowed_audio_types?: string[];
|
|
381
|
+
allowed_video_types?: string[];
|
|
382
|
+
}
|
|
383
|
+
/** Media input - URL reference */
|
|
384
|
+
export interface UrlMediaInput {
|
|
385
|
+
type: 'url';
|
|
386
|
+
url: string;
|
|
387
|
+
media_type?: string;
|
|
388
|
+
}
|
|
389
|
+
/** Media input - Base64 inline */
|
|
390
|
+
export interface Base64MediaInput {
|
|
391
|
+
type: 'base64';
|
|
392
|
+
media_type: string;
|
|
393
|
+
data: string;
|
|
394
|
+
}
|
|
395
|
+
/** Media input - File path */
|
|
396
|
+
export interface FileMediaInput {
|
|
397
|
+
type: 'file';
|
|
398
|
+
path: string;
|
|
399
|
+
}
|
|
400
|
+
/** Union of media input types */
|
|
401
|
+
export type MediaInput = UrlMediaInput | Base64MediaInput | FileMediaInput;
|
|
402
|
+
/** Media output with metadata */
|
|
403
|
+
export interface MediaOutput {
|
|
404
|
+
type: 'url' | 'base64' | 'file';
|
|
405
|
+
media_type: string;
|
|
406
|
+
url?: string;
|
|
407
|
+
data?: string;
|
|
408
|
+
path?: string;
|
|
409
|
+
width?: number;
|
|
410
|
+
height?: number;
|
|
411
|
+
duration_ms?: number;
|
|
412
|
+
expires_at?: string;
|
|
413
|
+
generation_params?: Record<string, unknown>;
|
|
414
|
+
}
|
|
415
|
+
/** Supported image MIME types */
|
|
416
|
+
export declare const SUPPORTED_IMAGE_TYPES: readonly ["image/jpeg", "image/png", "image/webp", "image/gif"];
|
|
417
|
+
/** Supported audio MIME types */
|
|
418
|
+
export declare const SUPPORTED_AUDIO_TYPES: readonly ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"];
|
|
419
|
+
/** Supported video MIME types */
|
|
420
|
+
export declare const SUPPORTED_VIDEO_TYPES: readonly ["video/mp4", "video/webm", "video/quicktime"];
|
|
421
|
+
/** v2.5 Error codes for streaming and multimodal */
|
|
422
|
+
export declare const ErrorCodesV25: {
|
|
423
|
+
readonly UNSUPPORTED_MEDIA_TYPE: "E1010";
|
|
424
|
+
readonly MEDIA_TOO_LARGE: "E1011";
|
|
425
|
+
readonly MEDIA_FETCH_FAILED: "E1012";
|
|
426
|
+
readonly MEDIA_DECODE_FAILED: "E1013";
|
|
427
|
+
readonly STREAM_INTERRUPTED: "E2010";
|
|
428
|
+
readonly STREAM_TIMEOUT: "E2011";
|
|
429
|
+
readonly STREAMING_NOT_SUPPORTED: "E4010";
|
|
430
|
+
readonly MULTIMODAL_NOT_SUPPORTED: "E4011";
|
|
431
|
+
};
|
|
432
|
+
export type ErrorCodeV25 = typeof ErrorCodesV25[keyof typeof ErrorCodesV25];
|
|
433
|
+
/** Runtime capability declaration */
|
|
434
|
+
export interface RuntimeCapabilities {
|
|
435
|
+
streaming: boolean;
|
|
436
|
+
multimodal: {
|
|
437
|
+
input: ModalityType[];
|
|
438
|
+
output: ModalityType[];
|
|
439
|
+
};
|
|
440
|
+
max_media_size_mb: number;
|
|
441
|
+
supported_transports: ('sse' | 'websocket' | 'ndjson')[];
|
|
442
|
+
}
|
|
443
|
+
/** Default runtime capabilities */
|
|
444
|
+
export declare const DEFAULT_RUNTIME_CAPABILITIES: RuntimeCapabilities;
|
|
445
|
+
/** Extended invoke params with streaming support */
|
|
446
|
+
export interface InvokeParamsV25 extends InvokeParams {
|
|
447
|
+
stream?: boolean;
|
|
448
|
+
images?: MediaInput[];
|
|
449
|
+
audio?: MediaInput[];
|
|
450
|
+
video?: MediaInput[];
|
|
451
|
+
}
|
|
452
|
+
/** Streaming invoke result */
|
|
453
|
+
export interface StreamingInvokeResult {
|
|
454
|
+
stream: AsyncIterable<string>;
|
|
455
|
+
usage?: {
|
|
456
|
+
promptTokens: number;
|
|
457
|
+
completionTokens: number;
|
|
458
|
+
totalTokens: number;
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
/** Extended provider interface for v2.5 */
|
|
462
|
+
export interface ProviderV25 extends Provider {
|
|
463
|
+
/** Check if provider supports streaming */
|
|
464
|
+
supportsStreaming?(): boolean;
|
|
465
|
+
/** Check if provider supports multimodal input */
|
|
466
|
+
supportsMultimodal?(): {
|
|
467
|
+
input: ModalityType[];
|
|
468
|
+
output: ModalityType[];
|
|
469
|
+
};
|
|
470
|
+
/** Invoke with streaming */
|
|
471
|
+
invokeStream?(params: InvokeParamsV25): Promise<StreamingInvokeResult>;
|
|
472
|
+
}
|
|
473
|
+
/** Type guard for v2.5 provider */
|
|
474
|
+
export declare function isProviderV25(provider: Provider): provider is ProviderV25;
|
|
475
|
+
/** Extended module interface for v2.5 */
|
|
476
|
+
export interface CognitiveModuleV25 extends CognitiveModule {
|
|
477
|
+
/** v2.5: Response configuration */
|
|
478
|
+
response?: ResponseConfig;
|
|
479
|
+
/** v2.5: Modalities configuration */
|
|
480
|
+
modalities?: ModalitiesConfig;
|
|
481
|
+
}
|
|
482
|
+
/** Type guard for v2.5 module */
|
|
483
|
+
export declare function isModuleV25(module: CognitiveModule): module is CognitiveModuleV25;
|
|
484
|
+
/** Check if module supports streaming */
|
|
485
|
+
export declare function moduleSupportsStreaming(module: CognitiveModule): boolean;
|
|
486
|
+
/** Check if module supports multimodal input */
|
|
487
|
+
export declare function moduleSupportsMultimodal(module: CognitiveModule): boolean;
|
|
488
|
+
/** Get supported input modalities for module */
|
|
489
|
+
export declare function getModuleInputModalities(module: CognitiveModule): ModalityType[];
|
|
490
|
+
/** Get supported output modalities for module */
|
|
491
|
+
export declare function getModuleOutputModalities(module: CognitiveModule): ModalityType[];
|
package/dist/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cognitive Runtime - Core Types
|
|
3
|
-
* Version 2.
|
|
3
|
+
* Version 2.5 - With streaming response and multimodal support
|
|
4
4
|
*/
|
|
5
5
|
// =============================================================================
|
|
6
6
|
// Utility Types
|
|
@@ -90,3 +90,84 @@ export function shouldEscalate(response, confidenceThreshold = 0.7) {
|
|
|
90
90
|
}
|
|
91
91
|
return false;
|
|
92
92
|
}
|
|
93
|
+
/** Supported image MIME types */
|
|
94
|
+
export const SUPPORTED_IMAGE_TYPES = [
|
|
95
|
+
'image/jpeg',
|
|
96
|
+
'image/png',
|
|
97
|
+
'image/webp',
|
|
98
|
+
'image/gif'
|
|
99
|
+
];
|
|
100
|
+
/** Supported audio MIME types */
|
|
101
|
+
export const SUPPORTED_AUDIO_TYPES = [
|
|
102
|
+
'audio/mpeg',
|
|
103
|
+
'audio/wav',
|
|
104
|
+
'audio/ogg',
|
|
105
|
+
'audio/webm'
|
|
106
|
+
];
|
|
107
|
+
/** Supported video MIME types */
|
|
108
|
+
export const SUPPORTED_VIDEO_TYPES = [
|
|
109
|
+
'video/mp4',
|
|
110
|
+
'video/webm',
|
|
111
|
+
'video/quicktime'
|
|
112
|
+
];
|
|
113
|
+
// =============================================================================
|
|
114
|
+
// v2.5 Error Codes
|
|
115
|
+
// =============================================================================
|
|
116
|
+
/** v2.5 Error codes for streaming and multimodal */
|
|
117
|
+
export const ErrorCodesV25 = {
|
|
118
|
+
// Media errors (E1xxx)
|
|
119
|
+
UNSUPPORTED_MEDIA_TYPE: 'E1010',
|
|
120
|
+
MEDIA_TOO_LARGE: 'E1011',
|
|
121
|
+
MEDIA_FETCH_FAILED: 'E1012',
|
|
122
|
+
MEDIA_DECODE_FAILED: 'E1013',
|
|
123
|
+
// Streaming errors (E2xxx)
|
|
124
|
+
STREAM_INTERRUPTED: 'E2010',
|
|
125
|
+
STREAM_TIMEOUT: 'E2011',
|
|
126
|
+
// Capability errors (E4xxx)
|
|
127
|
+
STREAMING_NOT_SUPPORTED: 'E4010',
|
|
128
|
+
MULTIMODAL_NOT_SUPPORTED: 'E4011',
|
|
129
|
+
};
|
|
130
|
+
/** Default runtime capabilities */
|
|
131
|
+
export const DEFAULT_RUNTIME_CAPABILITIES = {
|
|
132
|
+
streaming: true,
|
|
133
|
+
multimodal: {
|
|
134
|
+
input: ['text', 'image'],
|
|
135
|
+
output: ['text']
|
|
136
|
+
},
|
|
137
|
+
max_media_size_mb: 20,
|
|
138
|
+
supported_transports: ['sse', 'ndjson']
|
|
139
|
+
};
|
|
140
|
+
/** Type guard for v2.5 provider */
|
|
141
|
+
export function isProviderV25(provider) {
|
|
142
|
+
return 'invokeStream' in provider || 'supportsStreaming' in provider;
|
|
143
|
+
}
|
|
144
|
+
/** Type guard for v2.5 module */
|
|
145
|
+
export function isModuleV25(module) {
|
|
146
|
+
return 'response' in module || 'modalities' in module;
|
|
147
|
+
}
|
|
148
|
+
/** Check if module supports streaming */
|
|
149
|
+
export function moduleSupportsStreaming(module) {
|
|
150
|
+
if (!isModuleV25(module))
|
|
151
|
+
return false;
|
|
152
|
+
const mode = module.response?.mode;
|
|
153
|
+
return mode === 'streaming' || mode === 'both';
|
|
154
|
+
}
|
|
155
|
+
/** Check if module supports multimodal input */
|
|
156
|
+
export function moduleSupportsMultimodal(module) {
|
|
157
|
+
if (!isModuleV25(module))
|
|
158
|
+
return false;
|
|
159
|
+
const modalities = module.modalities?.input ?? ['text'];
|
|
160
|
+
return modalities.some(m => m !== 'text');
|
|
161
|
+
}
|
|
162
|
+
/** Get supported input modalities for module */
|
|
163
|
+
export function getModuleInputModalities(module) {
|
|
164
|
+
if (!isModuleV25(module))
|
|
165
|
+
return ['text'];
|
|
166
|
+
return module.modalities?.input ?? ['text'];
|
|
167
|
+
}
|
|
168
|
+
/** Get supported output modalities for module */
|
|
169
|
+
export function getModuleOutputModalities(module) {
|
|
170
|
+
if (!isModuleV25(module))
|
|
171
|
+
return ['text'];
|
|
172
|
+
return module.modalities?.output ?? ['text'];
|
|
173
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognitive-modules-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Cognitive Modules - Structured AI Task Execution with version management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -39,6 +39,9 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"js-yaml": "^4.1.1"
|
|
41
41
|
},
|
|
42
|
+
"optionalDependencies": {
|
|
43
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
44
|
+
},
|
|
42
45
|
"devDependencies": {
|
|
43
46
|
"@types/js-yaml": "^4.0.9",
|
|
44
47
|
"@types/node": "^22.0.0",
|
package/src/cli.ts
CHANGED
|
@@ -19,7 +19,7 @@ import { getProvider, listProviders } from './providers/index.js';
|
|
|
19
19
|
import { run, list, pipe, init, add, update, remove, versions } from './commands/index.js';
|
|
20
20
|
import type { CommandContext } from './types.js';
|
|
21
21
|
|
|
22
|
-
const VERSION = '1.0
|
|
22
|
+
const VERSION = '1.3.0';
|
|
23
23
|
|
|
24
24
|
async function main() {
|
|
25
25
|
const args = process.argv.slice(2);
|
|
@@ -52,6 +52,9 @@ async function main() {
|
|
|
52
52
|
tag: { type: 'string', short: 't' },
|
|
53
53
|
branch: { type: 'string', short: 'b' },
|
|
54
54
|
limit: { type: 'string', short: 'l' },
|
|
55
|
+
// Server options
|
|
56
|
+
host: { type: 'string', short: 'H' },
|
|
57
|
+
port: { type: 'string', short: 'P' },
|
|
55
58
|
},
|
|
56
59
|
allowPositionals: true,
|
|
57
60
|
});
|
|
@@ -288,6 +291,30 @@ async function main() {
|
|
|
288
291
|
break;
|
|
289
292
|
}
|
|
290
293
|
|
|
294
|
+
case 'serve': {
|
|
295
|
+
const { serve } = await import('./server/http.js');
|
|
296
|
+
const port = values.port ? parseInt(values.port as string, 10) : 8000;
|
|
297
|
+
const host = (values.host as string) || '0.0.0.0';
|
|
298
|
+
console.log('Starting Cognitive Modules HTTP Server...');
|
|
299
|
+
await serve({ host, port, cwd: ctx.cwd });
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
case 'mcp': {
|
|
304
|
+
try {
|
|
305
|
+
const { serve: serveMcp } = await import('./mcp/server.js');
|
|
306
|
+
await serveMcp();
|
|
307
|
+
} catch (e) {
|
|
308
|
+
if (e instanceof Error && e.message.includes('Cannot find module')) {
|
|
309
|
+
console.error('MCP dependencies not installed.');
|
|
310
|
+
console.error('Install with: npm install @modelcontextprotocol/sdk');
|
|
311
|
+
process.exit(1);
|
|
312
|
+
}
|
|
313
|
+
throw e;
|
|
314
|
+
}
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
|
|
291
318
|
default:
|
|
292
319
|
console.error(`Unknown command: ${command}`);
|
|
293
320
|
console.error('Run "cog --help" for usage.');
|
|
@@ -319,6 +346,8 @@ COMMANDS:
|
|
|
319
346
|
versions <url> List available versions
|
|
320
347
|
pipe Pipe mode (stdin/stdout)
|
|
321
348
|
init [name] Initialize project or create module
|
|
349
|
+
serve Start HTTP API server
|
|
350
|
+
mcp Start MCP server (for Claude Code, Cursor)
|
|
322
351
|
doctor Check configuration
|
|
323
352
|
|
|
324
353
|
OPTIONS:
|
|
@@ -333,6 +362,8 @@ OPTIONS:
|
|
|
333
362
|
--pretty Pretty-print JSON output
|
|
334
363
|
-V, --verbose Verbose output
|
|
335
364
|
--no-validate Skip schema validation
|
|
365
|
+
-H, --host <host> Server host (default: 0.0.0.0)
|
|
366
|
+
-P, --port <port> Server port (default: 8000)
|
|
336
367
|
-v, --version Show version
|
|
337
368
|
-h, --help Show this help
|
|
338
369
|
|
|
@@ -351,6 +382,10 @@ EXAMPLES:
|
|
|
351
382
|
cog run code-reviewer --provider openai --model gpt-4o --args "..."
|
|
352
383
|
cog list
|
|
353
384
|
|
|
385
|
+
# Servers
|
|
386
|
+
cog serve --port 8080
|
|
387
|
+
cog mcp
|
|
388
|
+
|
|
354
389
|
# Other
|
|
355
390
|
echo "review this code" | cog pipe --module code-reviewer
|
|
356
391
|
cog init my-module
|
package/src/index.ts
CHANGED
|
@@ -38,7 +38,18 @@ export {
|
|
|
38
38
|
listModules,
|
|
39
39
|
getDefaultSearchPaths,
|
|
40
40
|
runModule,
|
|
41
|
+
// Subagent
|
|
42
|
+
SubagentOrchestrator,
|
|
43
|
+
runWithSubagents,
|
|
44
|
+
parseCalls,
|
|
45
|
+
createContext,
|
|
41
46
|
} from './modules/index.js';
|
|
42
47
|
|
|
48
|
+
// Server
|
|
49
|
+
export { serve as serveHttp, createServer } from './server/index.js';
|
|
50
|
+
|
|
51
|
+
// MCP
|
|
52
|
+
export { serve as serveMcp } from './mcp/index.js';
|
|
53
|
+
|
|
43
54
|
// Commands
|
|
44
55
|
export { run, list, pipe } from './commands/index.js';
|