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.
- package/CHANGELOG.md +11 -0
- package/LICENSE +21 -0
- package/README.md +35 -29
- package/dist/cli.js +519 -23
- package/dist/commands/add.d.ts +33 -14
- package/dist/commands/add.js +383 -16
- package/dist/commands/compose.js +60 -23
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.js +4 -0
- package/dist/commands/init.js +23 -1
- package/dist/commands/migrate.d.ts +30 -0
- package/dist/commands/migrate.js +650 -0
- package/dist/commands/pipe.d.ts +1 -0
- package/dist/commands/pipe.js +31 -11
- package/dist/commands/remove.js +33 -2
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +61 -28
- package/dist/commands/search.d.ts +28 -0
- package/dist/commands/search.js +143 -0
- package/dist/commands/test.d.ts +65 -0
- package/dist/commands/test.js +454 -0
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +106 -14
- package/dist/commands/validate.d.ts +36 -0
- package/dist/commands/validate.js +97 -0
- package/dist/errors/index.d.ts +225 -0
- package/dist/errors/index.js +420 -0
- package/dist/mcp/server.js +84 -79
- package/dist/modules/composition.js +97 -32
- package/dist/modules/loader.js +4 -2
- package/dist/modules/runner.d.ts +72 -5
- package/dist/modules/runner.js +306 -59
- package/dist/modules/subagent.d.ts +6 -1
- package/dist/modules/subagent.js +18 -13
- package/dist/modules/validator.js +14 -6
- package/dist/providers/anthropic.d.ts +15 -0
- package/dist/providers/anthropic.js +147 -5
- package/dist/providers/base.d.ts +11 -0
- package/dist/providers/base.js +18 -0
- package/dist/providers/gemini.d.ts +15 -0
- package/dist/providers/gemini.js +122 -5
- package/dist/providers/ollama.d.ts +15 -0
- package/dist/providers/ollama.js +111 -3
- package/dist/providers/openai.d.ts +11 -0
- package/dist/providers/openai.js +133 -0
- package/dist/registry/client.d.ts +212 -0
- package/dist/registry/client.js +359 -0
- package/dist/registry/index.d.ts +4 -0
- package/dist/registry/index.js +4 -0
- package/dist/registry/tar.d.ts +8 -0
- package/dist/registry/tar.js +353 -0
- package/dist/server/http.js +301 -45
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +1 -0
- package/dist/server/sse.d.ts +13 -0
- package/dist/server/sse.js +22 -0
- package/dist/types.d.ts +32 -1
- package/dist/types.js +4 -1
- package/dist/version.d.ts +1 -0
- package/dist/version.js +4 -0
- package/package.json +31 -7
- package/dist/modules/composition.test.d.ts +0 -11
- package/dist/modules/composition.test.js +0 -450
- package/dist/modules/policy.test.d.ts +0 -10
- package/dist/modules/policy.test.js +0 -369
- package/src/cli.ts +0 -471
- package/src/commands/add.ts +0 -315
- package/src/commands/compose.ts +0 -185
- package/src/commands/index.ts +0 -13
- package/src/commands/init.ts +0 -94
- package/src/commands/list.ts +0 -33
- package/src/commands/pipe.ts +0 -76
- package/src/commands/remove.ts +0 -57
- package/src/commands/run.ts +0 -80
- package/src/commands/update.ts +0 -130
- package/src/commands/versions.ts +0 -79
- package/src/index.ts +0 -90
- package/src/mcp/index.ts +0 -5
- package/src/mcp/server.ts +0 -403
- package/src/modules/composition.test.ts +0 -558
- package/src/modules/composition.ts +0 -1674
- package/src/modules/index.ts +0 -9
- package/src/modules/loader.ts +0 -508
- package/src/modules/policy.test.ts +0 -455
- package/src/modules/runner.ts +0 -1983
- package/src/modules/subagent.ts +0 -277
- package/src/modules/validator.ts +0 -700
- package/src/providers/anthropic.ts +0 -89
- package/src/providers/base.ts +0 -29
- package/src/providers/deepseek.ts +0 -83
- package/src/providers/gemini.ts +0 -117
- package/src/providers/index.ts +0 -78
- package/src/providers/minimax.ts +0 -81
- package/src/providers/moonshot.ts +0 -82
- package/src/providers/ollama.ts +0 -83
- package/src/providers/openai.ts +0 -84
- package/src/providers/qwen.ts +0 -82
- package/src/server/http.ts +0 -316
- package/src/server/index.ts +0 -6
- package/src/types.ts +0 -599
- package/tsconfig.json +0 -17
package/dist/commands/pipe.js
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* cog pipe - Pipe mode for stdin/stdout integration
|
|
3
|
+
* Always returns v2.2 envelope format for consistency
|
|
3
4
|
*/
|
|
4
5
|
import * as readline from 'node:readline';
|
|
5
6
|
import { findModule, getDefaultSearchPaths, runModule } from '../modules/index.js';
|
|
7
|
+
import { ErrorCodes, attachContext, makeErrorEnvelope } from '../errors/index.js';
|
|
6
8
|
export async function pipe(ctx, options) {
|
|
7
9
|
const searchPaths = getDefaultSearchPaths(ctx.cwd);
|
|
8
10
|
// Find module
|
|
9
11
|
const module = await findModule(options.module, searchPaths);
|
|
10
12
|
if (!module) {
|
|
13
|
+
const errorEnvelope = attachContext(makeErrorEnvelope({
|
|
14
|
+
code: ErrorCodes.MODULE_NOT_FOUND,
|
|
15
|
+
message: `Module not found: ${options.module}`,
|
|
16
|
+
suggestion: "Use 'cog list' to see installed modules",
|
|
17
|
+
}), { module: options.module, provider: ctx.provider.name });
|
|
18
|
+
console.log(JSON.stringify(errorEnvelope));
|
|
11
19
|
return {
|
|
12
20
|
success: false,
|
|
13
|
-
error:
|
|
21
|
+
error: errorEnvelope.error.message,
|
|
22
|
+
data: errorEnvelope,
|
|
14
23
|
};
|
|
15
24
|
}
|
|
16
25
|
// Read from stdin
|
|
@@ -33,27 +42,38 @@ export async function pipe(ctx, options) {
|
|
|
33
42
|
catch {
|
|
34
43
|
// Not JSON, use as args
|
|
35
44
|
}
|
|
45
|
+
// Run module with v2.2 envelope format
|
|
36
46
|
const result = await runModule(module, ctx.provider, {
|
|
37
47
|
args: inputData ? undefined : input,
|
|
38
48
|
input: inputData,
|
|
49
|
+
validateInput: !options.noValidate,
|
|
50
|
+
validateOutput: !options.noValidate,
|
|
51
|
+
useV22: true, // Always use v2.2 envelope
|
|
39
52
|
});
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
const output = attachContext(result, {
|
|
54
|
+
module: options.module,
|
|
55
|
+
provider: ctx.provider.name,
|
|
56
|
+
});
|
|
57
|
+
// Output v2.2 envelope format to stdout
|
|
58
|
+
console.log(JSON.stringify(output));
|
|
42
59
|
return {
|
|
43
60
|
success: result.ok,
|
|
44
|
-
data:
|
|
61
|
+
data: output,
|
|
45
62
|
};
|
|
46
63
|
}
|
|
47
64
|
catch (e) {
|
|
48
|
-
const
|
|
49
|
-
// Output error
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
65
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
66
|
+
// Output v2.2 compliant error envelope
|
|
67
|
+
const errorEnvelope = attachContext(makeErrorEnvelope({
|
|
68
|
+
code: ErrorCodes.INTERNAL_ERROR,
|
|
69
|
+
message,
|
|
70
|
+
recoverable: false,
|
|
71
|
+
}), { module: options.module, provider: ctx.provider.name });
|
|
72
|
+
console.log(JSON.stringify(errorEnvelope));
|
|
54
73
|
return {
|
|
55
74
|
success: false,
|
|
56
|
-
error,
|
|
75
|
+
error: message,
|
|
76
|
+
data: errorEnvelope,
|
|
57
77
|
};
|
|
58
78
|
}
|
|
59
79
|
}
|
package/dist/commands/remove.js
CHANGED
|
@@ -5,15 +5,46 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { existsSync, rmSync } from 'node:fs';
|
|
7
7
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
8
|
-
import { join } from 'node:path';
|
|
8
|
+
import { join, resolve, sep, isAbsolute } from 'node:path';
|
|
9
9
|
import { homedir } from 'node:os';
|
|
10
10
|
const USER_MODULES_DIR = join(homedir(), '.cognitive', 'modules');
|
|
11
11
|
const INSTALLED_MANIFEST = join(homedir(), '.cognitive', 'installed.json');
|
|
12
|
+
function assertSafeModuleName(name) {
|
|
13
|
+
const trimmed = name.trim();
|
|
14
|
+
if (!trimmed) {
|
|
15
|
+
throw new Error('Invalid module name: empty');
|
|
16
|
+
}
|
|
17
|
+
if (trimmed.includes('..') || trimmed.includes('/') || trimmed.includes('\\')) {
|
|
18
|
+
throw new Error(`Invalid module name: ${name}`);
|
|
19
|
+
}
|
|
20
|
+
if (isAbsolute(trimmed)) {
|
|
21
|
+
throw new Error(`Invalid module name (absolute path not allowed): ${name}`);
|
|
22
|
+
}
|
|
23
|
+
return trimmed;
|
|
24
|
+
}
|
|
25
|
+
function resolveModuleTarget(moduleName) {
|
|
26
|
+
const safeName = assertSafeModuleName(moduleName);
|
|
27
|
+
const targetPath = resolve(USER_MODULES_DIR, safeName);
|
|
28
|
+
const root = resolve(USER_MODULES_DIR) + sep;
|
|
29
|
+
if (!targetPath.startsWith(root)) {
|
|
30
|
+
throw new Error(`Invalid module name (path traversal): ${moduleName}`);
|
|
31
|
+
}
|
|
32
|
+
return targetPath;
|
|
33
|
+
}
|
|
12
34
|
/**
|
|
13
35
|
* Remove an installed module
|
|
14
36
|
*/
|
|
15
37
|
export async function remove(moduleName, ctx) {
|
|
16
|
-
|
|
38
|
+
let modulePath;
|
|
39
|
+
try {
|
|
40
|
+
modulePath = resolveModuleTarget(moduleName);
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
error: e instanceof Error ? e.message : String(e),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
17
48
|
if (!existsSync(modulePath)) {
|
|
18
49
|
return {
|
|
19
50
|
success: false,
|
package/dist/commands/run.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* cog run - Run a Cognitive Module
|
|
3
|
+
* Always returns v2.2 envelope format for consistency
|
|
3
4
|
*/
|
|
4
5
|
import type { CommandContext, CommandResult } from '../types.js';
|
|
5
6
|
export interface RunOptions {
|
|
@@ -8,5 +9,6 @@ export interface RunOptions {
|
|
|
8
9
|
noValidate?: boolean;
|
|
9
10
|
pretty?: boolean;
|
|
10
11
|
verbose?: boolean;
|
|
12
|
+
stream?: boolean;
|
|
11
13
|
}
|
|
12
14
|
export declare function run(moduleName: string, ctx: CommandContext, options?: RunOptions): Promise<CommandResult>;
|
package/dist/commands/run.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* cog run - Run a Cognitive Module
|
|
3
|
+
* Always returns v2.2 envelope format for consistency
|
|
3
4
|
*/
|
|
4
|
-
import { findModule, getDefaultSearchPaths, runModule } from '../modules/index.js';
|
|
5
|
+
import { findModule, getDefaultSearchPaths, runModule, runModuleStream } from '../modules/index.js';
|
|
6
|
+
import { ErrorCodes, attachContext, makeErrorEnvelope } from '../errors/index.js';
|
|
5
7
|
export async function run(moduleName, ctx, options = {}) {
|
|
6
8
|
const searchPaths = getDefaultSearchPaths(ctx.cwd);
|
|
7
9
|
// Find module
|
|
8
10
|
const module = await findModule(moduleName, searchPaths);
|
|
9
11
|
if (!module) {
|
|
12
|
+
const errorEnvelope = attachContext(makeErrorEnvelope({
|
|
13
|
+
code: ErrorCodes.MODULE_NOT_FOUND,
|
|
14
|
+
message: `Module not found: ${moduleName}\nSearch paths: ${searchPaths.join(', ')}`,
|
|
15
|
+
suggestion: "Use 'cog list' to see installed modules or 'cog search' to find modules in registry",
|
|
16
|
+
}), { module: moduleName, provider: ctx.provider.name });
|
|
10
17
|
return {
|
|
11
18
|
success: false,
|
|
12
|
-
error:
|
|
19
|
+
error: errorEnvelope.error.message,
|
|
20
|
+
data: errorEnvelope,
|
|
13
21
|
};
|
|
14
22
|
}
|
|
15
23
|
try {
|
|
@@ -20,46 +28,71 @@ export async function run(moduleName, ctx, options = {}) {
|
|
|
20
28
|
inputData = JSON.parse(options.input);
|
|
21
29
|
}
|
|
22
30
|
catch {
|
|
31
|
+
const errorEnvelope = attachContext(makeErrorEnvelope({
|
|
32
|
+
code: ErrorCodes.INVALID_INPUT,
|
|
33
|
+
message: `Invalid JSON input: ${options.input}`,
|
|
34
|
+
suggestion: 'Ensure input is valid JSON format',
|
|
35
|
+
}), { module: moduleName, provider: ctx.provider.name });
|
|
23
36
|
return {
|
|
24
37
|
success: false,
|
|
25
|
-
error:
|
|
38
|
+
error: errorEnvelope.error.message,
|
|
39
|
+
data: errorEnvelope,
|
|
26
40
|
};
|
|
27
41
|
}
|
|
28
42
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
if (options.stream) {
|
|
44
|
+
// Stream NDJSON events to stdout. Final exit code is determined by the end event.
|
|
45
|
+
let finalOk = null;
|
|
46
|
+
for await (const ev of runModuleStream(module, ctx.provider, {
|
|
47
|
+
args: options.args,
|
|
48
|
+
input: inputData,
|
|
49
|
+
validateInput: !options.noValidate,
|
|
50
|
+
validateOutput: !options.noValidate,
|
|
51
|
+
useV22: true,
|
|
52
|
+
})) {
|
|
53
|
+
// Write each event as one JSON line (NDJSON).
|
|
54
|
+
process.stdout.write(JSON.stringify(ev) + '\n');
|
|
55
|
+
if (ev.type === 'end' && ev.result) {
|
|
56
|
+
finalOk = Boolean(ev.result.ok);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
37
59
|
return {
|
|
38
|
-
success:
|
|
39
|
-
data:
|
|
60
|
+
success: finalOk === true,
|
|
61
|
+
data: { ok: finalOk === true },
|
|
40
62
|
};
|
|
41
63
|
}
|
|
42
64
|
else {
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
65
|
+
// Run module with v2.2 envelope format
|
|
66
|
+
const result = await runModule(module, ctx.provider, {
|
|
67
|
+
args: options.args,
|
|
68
|
+
input: inputData,
|
|
69
|
+
verbose: options.verbose || ctx.verbose,
|
|
70
|
+
validateInput: !options.noValidate,
|
|
71
|
+
validateOutput: !options.noValidate,
|
|
72
|
+
useV22: true, // Always use v2.2 envelope
|
|
73
|
+
});
|
|
74
|
+
const output = attachContext(result, {
|
|
75
|
+
module: moduleName,
|
|
76
|
+
provider: ctx.provider.name,
|
|
77
|
+
});
|
|
78
|
+
// Always return full v2.2 envelope
|
|
79
|
+
return {
|
|
80
|
+
success: result.ok,
|
|
81
|
+
data: output,
|
|
82
|
+
};
|
|
57
83
|
}
|
|
58
84
|
}
|
|
59
85
|
catch (e) {
|
|
86
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
87
|
+
const errorEnvelope = attachContext(makeErrorEnvelope({
|
|
88
|
+
code: ErrorCodes.INTERNAL_ERROR,
|
|
89
|
+
message,
|
|
90
|
+
recoverable: false,
|
|
91
|
+
}), { module: moduleName, provider: ctx.provider.name });
|
|
60
92
|
return {
|
|
61
93
|
success: false,
|
|
62
|
-
error:
|
|
94
|
+
error: message,
|
|
95
|
+
data: errorEnvelope,
|
|
63
96
|
};
|
|
64
97
|
}
|
|
65
98
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search command - Search for modules in the registry
|
|
3
|
+
*
|
|
4
|
+
* cog search code review
|
|
5
|
+
* cog search --category code-quality
|
|
6
|
+
*/
|
|
7
|
+
import type { CommandContext, CommandResult } from '../types.js';
|
|
8
|
+
export interface SearchOptions {
|
|
9
|
+
category?: string;
|
|
10
|
+
limit?: number;
|
|
11
|
+
registry?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Search for modules in the registry
|
|
15
|
+
*/
|
|
16
|
+
export declare function search(query: string, ctx: CommandContext, options?: SearchOptions): Promise<CommandResult>;
|
|
17
|
+
/**
|
|
18
|
+
* List all categories
|
|
19
|
+
*/
|
|
20
|
+
export declare function listCategories(ctx: CommandContext, options?: {
|
|
21
|
+
registry?: string;
|
|
22
|
+
}): Promise<CommandResult>;
|
|
23
|
+
/**
|
|
24
|
+
* Get detailed info about a module from registry
|
|
25
|
+
*/
|
|
26
|
+
export declare function info(moduleName: string, ctx: CommandContext, options?: {
|
|
27
|
+
registry?: string;
|
|
28
|
+
}): Promise<CommandResult>;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search command - Search for modules in the registry
|
|
3
|
+
*
|
|
4
|
+
* cog search code review
|
|
5
|
+
* cog search --category code-quality
|
|
6
|
+
*/
|
|
7
|
+
import { RegistryClient } from '../registry/client.js';
|
|
8
|
+
/**
|
|
9
|
+
* Search for modules in the registry
|
|
10
|
+
*/
|
|
11
|
+
export async function search(query, ctx, options = {}) {
|
|
12
|
+
const { category, limit = 20, registry } = options;
|
|
13
|
+
try {
|
|
14
|
+
const client = new RegistryClient(registry);
|
|
15
|
+
let results;
|
|
16
|
+
if (category) {
|
|
17
|
+
// Search within category
|
|
18
|
+
const categories = await client.getCategories();
|
|
19
|
+
const cat = categories[category];
|
|
20
|
+
if (!cat) {
|
|
21
|
+
return {
|
|
22
|
+
success: false,
|
|
23
|
+
error: `Category not found: ${category}\nAvailable categories: ${Object.keys(categories).join(', ')}`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
// Get modules in category
|
|
27
|
+
const modules = [];
|
|
28
|
+
for (const name of cat.modules) {
|
|
29
|
+
const mod = await client.getModule(name);
|
|
30
|
+
if (mod) {
|
|
31
|
+
modules.push(mod);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// If query provided, filter by query
|
|
35
|
+
if (query) {
|
|
36
|
+
results = modules
|
|
37
|
+
.filter(m => m.name.toLowerCase().includes(query.toLowerCase()) ||
|
|
38
|
+
m.description.toLowerCase().includes(query.toLowerCase()))
|
|
39
|
+
.map(m => ({
|
|
40
|
+
name: m.name,
|
|
41
|
+
description: m.description,
|
|
42
|
+
version: m.version,
|
|
43
|
+
score: 1,
|
|
44
|
+
keywords: m.keywords,
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
results = modules.map(m => ({
|
|
49
|
+
name: m.name,
|
|
50
|
+
description: m.description,
|
|
51
|
+
version: m.version,
|
|
52
|
+
score: 1,
|
|
53
|
+
keywords: m.keywords,
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else if (query) {
|
|
58
|
+
// Search by query
|
|
59
|
+
results = await client.search(query);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// List all modules
|
|
63
|
+
const modules = await client.listModules();
|
|
64
|
+
results = modules.map(m => ({
|
|
65
|
+
name: m.name,
|
|
66
|
+
description: m.description,
|
|
67
|
+
version: m.version,
|
|
68
|
+
score: 1,
|
|
69
|
+
keywords: m.keywords,
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
// Apply limit
|
|
73
|
+
const limited = results.slice(0, limit);
|
|
74
|
+
return {
|
|
75
|
+
success: true,
|
|
76
|
+
data: {
|
|
77
|
+
query,
|
|
78
|
+
category,
|
|
79
|
+
total: results.length,
|
|
80
|
+
results: limited,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
error: error instanceof Error ? error.message : String(error),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* List all categories
|
|
93
|
+
*/
|
|
94
|
+
export async function listCategories(ctx, options = {}) {
|
|
95
|
+
try {
|
|
96
|
+
const client = new RegistryClient(options.registry);
|
|
97
|
+
const categories = await client.getCategories();
|
|
98
|
+
return {
|
|
99
|
+
success: true,
|
|
100
|
+
data: {
|
|
101
|
+
categories: Object.entries(categories).map(([key, cat]) => ({
|
|
102
|
+
key,
|
|
103
|
+
name: cat.name,
|
|
104
|
+
description: cat.description,
|
|
105
|
+
moduleCount: cat.modules.length,
|
|
106
|
+
})),
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return {
|
|
112
|
+
success: false,
|
|
113
|
+
error: error instanceof Error ? error.message : String(error),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get detailed info about a module from registry
|
|
119
|
+
*/
|
|
120
|
+
export async function info(moduleName, ctx, options = {}) {
|
|
121
|
+
try {
|
|
122
|
+
const client = new RegistryClient(options.registry);
|
|
123
|
+
const module = await client.getModule(moduleName);
|
|
124
|
+
if (!module) {
|
|
125
|
+
return {
|
|
126
|
+
success: false,
|
|
127
|
+
error: `Module not found in registry: ${moduleName}`,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
success: true,
|
|
132
|
+
data: {
|
|
133
|
+
module,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
return {
|
|
139
|
+
success: false,
|
|
140
|
+
error: error instanceof Error ? error.message : String(error),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Command - Run golden tests for Cognitive Modules
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* cog test <module> - Run tests for a specific module
|
|
6
|
+
* cog test --all - Run tests for all modules
|
|
7
|
+
* cog test <module> --update - Update expected outputs
|
|
8
|
+
*
|
|
9
|
+
* Tests are defined in module.yaml:
|
|
10
|
+
* tests:
|
|
11
|
+
* - tests/case1.input.json -> tests/case1.expected.json
|
|
12
|
+
*/
|
|
13
|
+
import type { CommandContext, CommandResult, CognitiveModule } from '../types.js';
|
|
14
|
+
export interface TestCase {
|
|
15
|
+
name: string;
|
|
16
|
+
inputPath: string;
|
|
17
|
+
expectedPath: string;
|
|
18
|
+
input?: unknown;
|
|
19
|
+
expected?: unknown;
|
|
20
|
+
}
|
|
21
|
+
export interface TestResult {
|
|
22
|
+
name: string;
|
|
23
|
+
passed: boolean;
|
|
24
|
+
duration_ms: number;
|
|
25
|
+
error?: string;
|
|
26
|
+
diff?: {
|
|
27
|
+
field: string;
|
|
28
|
+
expected: unknown;
|
|
29
|
+
actual: unknown;
|
|
30
|
+
}[];
|
|
31
|
+
}
|
|
32
|
+
export interface ModuleTestResult {
|
|
33
|
+
moduleName: string;
|
|
34
|
+
modulePath: string;
|
|
35
|
+
total: number;
|
|
36
|
+
passed: number;
|
|
37
|
+
failed: number;
|
|
38
|
+
skipped: number;
|
|
39
|
+
duration_ms: number;
|
|
40
|
+
results: TestResult[];
|
|
41
|
+
}
|
|
42
|
+
export interface TestOptions {
|
|
43
|
+
verbose?: boolean;
|
|
44
|
+
update?: boolean;
|
|
45
|
+
filter?: string;
|
|
46
|
+
timeout?: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parse test definitions from module.yaml tests field
|
|
50
|
+
*
|
|
51
|
+
* Format: "tests/case1.input.json -> tests/case1.expected.json"
|
|
52
|
+
*/
|
|
53
|
+
export declare function parseTestDefinitions(module: CognitiveModule, modulePath: string): TestCase[];
|
|
54
|
+
/**
|
|
55
|
+
* Auto-discover test cases in tests/ directory
|
|
56
|
+
*/
|
|
57
|
+
export declare function discoverTestCases(modulePath: string): TestCase[];
|
|
58
|
+
/**
|
|
59
|
+
* Run tests for a single module
|
|
60
|
+
*/
|
|
61
|
+
export declare function test(moduleName: string, ctx: CommandContext, options?: TestOptions): Promise<CommandResult>;
|
|
62
|
+
/**
|
|
63
|
+
* Run tests for all modules
|
|
64
|
+
*/
|
|
65
|
+
export declare function testAll(ctx: CommandContext, options?: TestOptions): Promise<CommandResult>;
|