cognitive-runtime 0.3.0 → 0.5.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 +39 -0
- package/dist/cli.js +1 -1
- package/dist/commands/pipe.js +8 -6
- package/dist/commands/run.js +23 -6
- package/dist/index.d.ts +1 -1
- package/dist/modules/loader.d.ts +4 -0
- package/dist/modules/loader.js +121 -15
- package/dist/modules/runner.d.ts +4 -4
- package/dist/modules/runner.js +186 -50
- package/dist/types.d.ts +83 -0
- package/dist/types.js +1 -0
- package/package.json +1 -1
- package/src/cli.ts +1 -1
- package/src/commands/pipe.ts +8 -6
- package/src/commands/run.ts +21 -6
- package/src/index.ts +5 -0
- package/src/modules/loader.ts +127 -14
- package/src/modules/runner.ts +211 -54
- package/src/types.ts +121 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cognitive Runtime - Core Types
|
|
3
|
+
* Version 2.1 - With envelope format, tools policy, failure contract
|
|
3
4
|
*/
|
|
4
5
|
export interface Provider {
|
|
5
6
|
name: string;
|
|
@@ -29,16 +30,91 @@ export interface CognitiveModule {
|
|
|
29
30
|
version: string;
|
|
30
31
|
responsibility: string;
|
|
31
32
|
excludes: string[];
|
|
33
|
+
constraints?: ModuleConstraints;
|
|
34
|
+
policies?: ModulePolicies;
|
|
35
|
+
tools?: ToolsPolicy;
|
|
36
|
+
output?: OutputContract;
|
|
37
|
+
failure?: FailureContract;
|
|
38
|
+
runtimeRequirements?: RuntimeRequirements;
|
|
32
39
|
context?: 'fork' | 'main';
|
|
33
40
|
prompt: string;
|
|
34
41
|
inputSchema?: object;
|
|
35
42
|
outputSchema?: object;
|
|
43
|
+
errorSchema?: object;
|
|
36
44
|
location: string;
|
|
45
|
+
format: 'v1' | 'v2';
|
|
46
|
+
}
|
|
47
|
+
export interface ModuleConstraints {
|
|
48
|
+
no_network?: boolean;
|
|
49
|
+
no_side_effects?: boolean;
|
|
50
|
+
no_file_write?: boolean;
|
|
51
|
+
no_inventing_data?: boolean;
|
|
52
|
+
behavior_equivalence_false_max_confidence?: number;
|
|
53
|
+
}
|
|
54
|
+
export interface ModulePolicies {
|
|
55
|
+
network?: 'allow' | 'deny';
|
|
56
|
+
filesystem_write?: 'allow' | 'deny';
|
|
57
|
+
side_effects?: 'allow' | 'deny';
|
|
58
|
+
code_execution?: 'allow' | 'deny';
|
|
59
|
+
}
|
|
60
|
+
export interface ToolsPolicy {
|
|
61
|
+
policy?: 'allow_by_default' | 'deny_by_default';
|
|
62
|
+
allowed: string[];
|
|
63
|
+
denied?: string[];
|
|
64
|
+
}
|
|
65
|
+
export interface OutputContract {
|
|
66
|
+
format?: 'json_strict' | 'json_lenient' | 'text';
|
|
67
|
+
envelope?: boolean;
|
|
68
|
+
require?: string[];
|
|
69
|
+
require_confidence?: boolean;
|
|
70
|
+
require_rationale?: boolean;
|
|
71
|
+
require_behavior_equivalence?: boolean;
|
|
72
|
+
}
|
|
73
|
+
export interface FailureContract {
|
|
74
|
+
contract?: 'error_union' | 'throw';
|
|
75
|
+
partial_allowed?: boolean;
|
|
76
|
+
must_return_error_schema?: boolean;
|
|
77
|
+
schema?: object;
|
|
78
|
+
}
|
|
79
|
+
export interface RuntimeRequirements {
|
|
80
|
+
structured_output?: boolean;
|
|
81
|
+
max_input_tokens?: number;
|
|
82
|
+
preferred_capabilities?: string[];
|
|
83
|
+
}
|
|
84
|
+
export interface EnvelopeSuccess<T = unknown> {
|
|
85
|
+
ok: true;
|
|
86
|
+
data: T;
|
|
87
|
+
}
|
|
88
|
+
export interface EnvelopeError {
|
|
89
|
+
ok: false;
|
|
90
|
+
error: {
|
|
91
|
+
code: string;
|
|
92
|
+
message: string;
|
|
93
|
+
};
|
|
94
|
+
partial_data?: unknown;
|
|
95
|
+
}
|
|
96
|
+
export type EnvelopeResponse<T = unknown> = EnvelopeSuccess<T> | EnvelopeError;
|
|
97
|
+
export interface ModuleResultData {
|
|
98
|
+
[key: string]: unknown;
|
|
99
|
+
confidence: number;
|
|
100
|
+
rationale: string;
|
|
101
|
+
behavior_equivalence?: boolean;
|
|
37
102
|
}
|
|
38
103
|
export interface ModuleResult {
|
|
104
|
+
ok: boolean;
|
|
105
|
+
data?: ModuleResultData;
|
|
106
|
+
error?: {
|
|
107
|
+
code: string;
|
|
108
|
+
message: string;
|
|
109
|
+
};
|
|
110
|
+
partial_data?: unknown;
|
|
111
|
+
raw?: string;
|
|
112
|
+
}
|
|
113
|
+
export interface LegacyModuleResult {
|
|
39
114
|
output: unknown;
|
|
40
115
|
confidence: number;
|
|
41
116
|
rationale: string;
|
|
117
|
+
behaviorEquivalence?: boolean;
|
|
42
118
|
raw?: string;
|
|
43
119
|
}
|
|
44
120
|
export interface CommandContext {
|
|
@@ -51,3 +127,10 @@ export interface CommandResult {
|
|
|
51
127
|
data?: unknown;
|
|
52
128
|
error?: string;
|
|
53
129
|
}
|
|
130
|
+
export interface ModuleInput {
|
|
131
|
+
code?: string;
|
|
132
|
+
query?: string;
|
|
133
|
+
language?: string;
|
|
134
|
+
options?: Record<string, unknown>;
|
|
135
|
+
[key: string]: unknown;
|
|
136
|
+
}
|
package/dist/types.js
CHANGED
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { getProvider, listProviders } from './providers/index.js';
|
|
|
13
13
|
import { run, list, pipe, init } from './commands/index.js';
|
|
14
14
|
import type { CommandContext } from './types.js';
|
|
15
15
|
|
|
16
|
-
const VERSION = '0.
|
|
16
|
+
const VERSION = '0.5.0';
|
|
17
17
|
|
|
18
18
|
async function main() {
|
|
19
19
|
const args = process.argv.slice(2);
|
package/src/commands/pipe.ts
CHANGED
|
@@ -52,20 +52,22 @@ export async function pipe(
|
|
|
52
52
|
const result = await runModule(module, ctx.provider, {
|
|
53
53
|
args: inputData ? undefined : input,
|
|
54
54
|
input: inputData,
|
|
55
|
-
validateInput: !options.noValidate,
|
|
56
|
-
validateOutput: !options.noValidate,
|
|
57
55
|
});
|
|
58
56
|
|
|
59
|
-
// Output
|
|
60
|
-
console.log(JSON.stringify(result
|
|
57
|
+
// Output envelope format to stdout
|
|
58
|
+
console.log(JSON.stringify(result));
|
|
61
59
|
|
|
62
60
|
return {
|
|
63
|
-
success:
|
|
61
|
+
success: result.ok,
|
|
64
62
|
data: result,
|
|
65
63
|
};
|
|
66
64
|
} catch (e) {
|
|
67
65
|
const error = e instanceof Error ? e.message : String(e);
|
|
68
|
-
|
|
66
|
+
// Output error in envelope format
|
|
67
|
+
console.log(JSON.stringify({
|
|
68
|
+
ok: false,
|
|
69
|
+
error: { code: 'RUNTIME_ERROR', message: error }
|
|
70
|
+
}));
|
|
69
71
|
return {
|
|
70
72
|
success: false,
|
|
71
73
|
error,
|
package/src/commands/run.ts
CHANGED
|
@@ -47,15 +47,30 @@ export async function run(
|
|
|
47
47
|
const result = await runModule(module, ctx.provider, {
|
|
48
48
|
args: options.args,
|
|
49
49
|
input: inputData,
|
|
50
|
-
validateInput: !options.noValidate,
|
|
51
|
-
validateOutput: !options.noValidate,
|
|
52
50
|
verbose: options.verbose || ctx.verbose,
|
|
53
51
|
});
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
// Return envelope format or extracted data
|
|
54
|
+
if (options.pretty) {
|
|
55
|
+
return {
|
|
56
|
+
success: result.ok,
|
|
57
|
+
data: result,
|
|
58
|
+
};
|
|
59
|
+
} else {
|
|
60
|
+
// For non-pretty mode, return data (success) or error (failure)
|
|
61
|
+
if (result.ok) {
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
data: result.data,
|
|
65
|
+
};
|
|
66
|
+
} else {
|
|
67
|
+
return {
|
|
68
|
+
success: false,
|
|
69
|
+
error: `${result.error?.code}: ${result.error?.message}`,
|
|
70
|
+
data: result.partial_data,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
59
74
|
} catch (e) {
|
|
60
75
|
return {
|
|
61
76
|
success: false,
|
package/src/index.ts
CHANGED
package/src/modules/loader.ts
CHANGED
|
@@ -1,15 +1,88 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Module Loader - Load and parse Cognitive Modules
|
|
3
|
+
* Supports both v1 (MODULE.md) and v2 (module.yaml + prompt.md) formats
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
import * as fs from 'node:fs/promises';
|
|
6
7
|
import * as path from 'node:path';
|
|
7
8
|
import yaml from 'js-yaml';
|
|
8
|
-
import type { CognitiveModule } from '../types.js';
|
|
9
|
+
import type { CognitiveModule, ModuleConstraints, ModulePolicies, ToolsPolicy, OutputContract, FailureContract, RuntimeRequirements } from '../types.js';
|
|
9
10
|
|
|
10
11
|
const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n([\s\S]*))?/;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Detect module format version
|
|
15
|
+
*/
|
|
16
|
+
async function detectFormat(modulePath: string): Promise<'v1' | 'v2'> {
|
|
17
|
+
const v2Manifest = path.join(modulePath, 'module.yaml');
|
|
18
|
+
try {
|
|
19
|
+
await fs.access(v2Manifest);
|
|
20
|
+
return 'v2';
|
|
21
|
+
} catch {
|
|
22
|
+
return 'v1';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Load v2 format module (module.yaml + prompt.md)
|
|
28
|
+
*/
|
|
29
|
+
async function loadModuleV2(modulePath: string): Promise<CognitiveModule> {
|
|
30
|
+
const manifestFile = path.join(modulePath, 'module.yaml');
|
|
31
|
+
const promptFile = path.join(modulePath, 'prompt.md');
|
|
32
|
+
const schemaFile = path.join(modulePath, 'schema.json');
|
|
33
|
+
|
|
34
|
+
// Read module.yaml
|
|
35
|
+
const manifestContent = await fs.readFile(manifestFile, 'utf-8');
|
|
36
|
+
const manifest = yaml.load(manifestContent) as Record<string, unknown>;
|
|
37
|
+
|
|
38
|
+
// Read prompt.md
|
|
39
|
+
let prompt = '';
|
|
40
|
+
try {
|
|
41
|
+
prompt = await fs.readFile(promptFile, 'utf-8');
|
|
42
|
+
} catch {
|
|
43
|
+
// prompt.md is optional, manifest may include inline prompt
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Read schema.json
|
|
47
|
+
let inputSchema: object | undefined;
|
|
48
|
+
let outputSchema: object | undefined;
|
|
49
|
+
let errorSchema: object | undefined;
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const schemaContent = await fs.readFile(schemaFile, 'utf-8');
|
|
53
|
+
const schema = JSON.parse(schemaContent);
|
|
54
|
+
inputSchema = schema.input;
|
|
55
|
+
outputSchema = schema.output;
|
|
56
|
+
errorSchema = schema.error;
|
|
57
|
+
} catch {
|
|
58
|
+
// Schema file is optional but recommended
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
name: manifest.name as string || path.basename(modulePath),
|
|
63
|
+
version: manifest.version as string || '1.0.0',
|
|
64
|
+
responsibility: manifest.responsibility as string || '',
|
|
65
|
+
excludes: (manifest.excludes as string[]) || [],
|
|
66
|
+
constraints: manifest.constraints as ModuleConstraints | undefined,
|
|
67
|
+
policies: manifest.policies as ModulePolicies | undefined,
|
|
68
|
+
tools: manifest.tools as ToolsPolicy | undefined,
|
|
69
|
+
output: manifest.output as OutputContract | undefined,
|
|
70
|
+
failure: manifest.failure as FailureContract | undefined,
|
|
71
|
+
runtimeRequirements: manifest.runtime_requirements as RuntimeRequirements | undefined,
|
|
72
|
+
context: manifest.context as 'fork' | 'main' | undefined,
|
|
73
|
+
prompt,
|
|
74
|
+
inputSchema,
|
|
75
|
+
outputSchema,
|
|
76
|
+
errorSchema,
|
|
77
|
+
location: modulePath,
|
|
78
|
+
format: 'v2',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Load v1 format module (MODULE.md with frontmatter)
|
|
84
|
+
*/
|
|
85
|
+
async function loadModuleV1(modulePath: string): Promise<CognitiveModule> {
|
|
13
86
|
const moduleFile = path.join(modulePath, 'MODULE.md');
|
|
14
87
|
const schemaFile = path.join(modulePath, 'schema.json');
|
|
15
88
|
|
|
@@ -38,29 +111,69 @@ export async function loadModule(modulePath: string): Promise<CognitiveModule> {
|
|
|
38
111
|
// Schema file is optional
|
|
39
112
|
}
|
|
40
113
|
|
|
114
|
+
// Extract constraints from v1 format
|
|
115
|
+
const constraints: ModuleConstraints = {};
|
|
116
|
+
const v1Constraints = frontmatter.constraints as Record<string, boolean> | undefined;
|
|
117
|
+
if (v1Constraints) {
|
|
118
|
+
constraints.no_network = v1Constraints.no_network;
|
|
119
|
+
constraints.no_side_effects = v1Constraints.no_side_effects;
|
|
120
|
+
constraints.no_inventing_data = v1Constraints.no_inventing_data;
|
|
121
|
+
}
|
|
122
|
+
|
|
41
123
|
return {
|
|
42
124
|
name: frontmatter.name as string || path.basename(modulePath),
|
|
43
125
|
version: frontmatter.version as string || '1.0.0',
|
|
44
126
|
responsibility: frontmatter.responsibility as string || '',
|
|
45
127
|
excludes: (frontmatter.excludes as string[]) || [],
|
|
128
|
+
constraints: Object.keys(constraints).length > 0 ? constraints : undefined,
|
|
46
129
|
context: frontmatter.context as 'fork' | 'main' | undefined,
|
|
47
130
|
prompt,
|
|
48
131
|
inputSchema,
|
|
49
132
|
outputSchema,
|
|
50
133
|
location: modulePath,
|
|
134
|
+
format: 'v1',
|
|
51
135
|
};
|
|
52
136
|
}
|
|
53
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Load a Cognitive Module (auto-detects format)
|
|
140
|
+
*/
|
|
141
|
+
export async function loadModule(modulePath: string): Promise<CognitiveModule> {
|
|
142
|
+
const format = await detectFormat(modulePath);
|
|
143
|
+
|
|
144
|
+
if (format === 'v2') {
|
|
145
|
+
return loadModuleV2(modulePath);
|
|
146
|
+
} else {
|
|
147
|
+
return loadModuleV1(modulePath);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Check if a directory contains a valid module
|
|
153
|
+
*/
|
|
154
|
+
async function isValidModule(modulePath: string): Promise<boolean> {
|
|
155
|
+
const v2Manifest = path.join(modulePath, 'module.yaml');
|
|
156
|
+
const v1Module = path.join(modulePath, 'MODULE.md');
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
await fs.access(v2Manifest);
|
|
160
|
+
return true;
|
|
161
|
+
} catch {
|
|
162
|
+
try {
|
|
163
|
+
await fs.access(v1Module);
|
|
164
|
+
return true;
|
|
165
|
+
} catch {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
54
171
|
export async function findModule(name: string, searchPaths: string[]): Promise<CognitiveModule | null> {
|
|
55
172
|
for (const basePath of searchPaths) {
|
|
56
173
|
const modulePath = path.join(basePath, name);
|
|
57
|
-
const moduleFile = path.join(modulePath, 'MODULE.md');
|
|
58
174
|
|
|
59
|
-
|
|
60
|
-
await fs.access(moduleFile);
|
|
175
|
+
if (await isValidModule(modulePath)) {
|
|
61
176
|
return await loadModule(modulePath);
|
|
62
|
-
} catch {
|
|
63
|
-
// Module not found in this path, continue
|
|
64
177
|
}
|
|
65
178
|
}
|
|
66
179
|
|
|
@@ -77,14 +190,14 @@ export async function listModules(searchPaths: string[]): Promise<CognitiveModul
|
|
|
77
190
|
for (const entry of entries) {
|
|
78
191
|
if (entry.isDirectory()) {
|
|
79
192
|
const modulePath = path.join(basePath, entry.name);
|
|
80
|
-
const moduleFile = path.join(modulePath, 'MODULE.md');
|
|
81
193
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
194
|
+
if (await isValidModule(modulePath)) {
|
|
195
|
+
try {
|
|
196
|
+
const module = await loadModule(modulePath);
|
|
197
|
+
modules.push(module);
|
|
198
|
+
} catch {
|
|
199
|
+
// Skip invalid modules
|
|
200
|
+
}
|
|
88
201
|
}
|
|
89
202
|
}
|
|
90
203
|
}
|