cognitive-runtime 0.4.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 -4
- package/dist/commands/run.js +23 -4
- package/dist/modules/loader.js +2 -0
- package/dist/modules/runner.d.ts +2 -1
- package/dist/modules/runner.js +95 -15
- package/dist/types.d.ts +52 -2
- package/dist/types.js +1 -1
- package/package.json +1 -1
- package/src/cli.ts +1 -1
- package/src/commands/pipe.ts +8 -4
- package/src/commands/run.ts +21 -4
- package/src/modules/loader.ts +3 -1
- package/src/modules/runner.ts +111 -16
- package/src/types.ts +67 -3
package/README.md
CHANGED
|
@@ -65,6 +65,45 @@ echo "review this code" | cog pipe --module code-reviewer
|
|
|
65
65
|
cog doctor
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
## Module Formats
|
|
69
|
+
|
|
70
|
+
### v2 (Recommended)
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
my-module/
|
|
74
|
+
├── module.yaml # Machine-readable manifest
|
|
75
|
+
├── prompt.md # Human-readable prompt
|
|
76
|
+
├── schema.json # IO contract
|
|
77
|
+
└── tests/
|
|
78
|
+
├── case1.input.json
|
|
79
|
+
└── case1.expected.json
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**module.yaml**:
|
|
83
|
+
```yaml
|
|
84
|
+
name: my-module
|
|
85
|
+
version: 2.0.0
|
|
86
|
+
responsibility: What this module does
|
|
87
|
+
constraints:
|
|
88
|
+
no_network: true
|
|
89
|
+
no_side_effects: true
|
|
90
|
+
output:
|
|
91
|
+
mode: json_strict
|
|
92
|
+
require_confidence: true
|
|
93
|
+
require_rationale: true
|
|
94
|
+
require_behavior_equivalence: true
|
|
95
|
+
tools:
|
|
96
|
+
allowed: []
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### v1 (Legacy, still supported)
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
my-module/
|
|
103
|
+
├── MODULE.md # Frontmatter + prompt combined
|
|
104
|
+
└── schema.json
|
|
105
|
+
```
|
|
106
|
+
|
|
68
107
|
## Providers
|
|
69
108
|
|
|
70
109
|
| Provider | Environment Variable | Default Model |
|
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { parseArgs } from 'node:util';
|
|
11
11
|
import { getProvider, listProviders } from './providers/index.js';
|
|
12
12
|
import { run, list, pipe, init } from './commands/index.js';
|
|
13
|
-
const VERSION = '0.
|
|
13
|
+
const VERSION = '0.5.0';
|
|
14
14
|
async function main() {
|
|
15
15
|
const args = process.argv.slice(2);
|
|
16
16
|
const command = args[0];
|
package/dist/commands/pipe.js
CHANGED
|
@@ -37,16 +37,20 @@ export async function pipe(ctx, options) {
|
|
|
37
37
|
args: inputData ? undefined : input,
|
|
38
38
|
input: inputData,
|
|
39
39
|
});
|
|
40
|
-
// Output
|
|
41
|
-
console.log(JSON.stringify(result
|
|
40
|
+
// Output envelope format to stdout
|
|
41
|
+
console.log(JSON.stringify(result));
|
|
42
42
|
return {
|
|
43
|
-
success:
|
|
43
|
+
success: result.ok,
|
|
44
44
|
data: result,
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
catch (e) {
|
|
48
48
|
const error = e instanceof Error ? e.message : String(e);
|
|
49
|
-
|
|
49
|
+
// Output error in envelope format
|
|
50
|
+
console.log(JSON.stringify({
|
|
51
|
+
ok: false,
|
|
52
|
+
error: { code: 'RUNTIME_ERROR', message: error }
|
|
53
|
+
}));
|
|
50
54
|
return {
|
|
51
55
|
success: false,
|
|
52
56
|
error,
|
package/dist/commands/run.js
CHANGED
|
@@ -32,10 +32,29 @@ export async function run(moduleName, ctx, options = {}) {
|
|
|
32
32
|
input: inputData,
|
|
33
33
|
verbose: options.verbose || ctx.verbose,
|
|
34
34
|
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
// Return envelope format or extracted data
|
|
36
|
+
if (options.pretty) {
|
|
37
|
+
return {
|
|
38
|
+
success: result.ok,
|
|
39
|
+
data: result,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// For non-pretty mode, return data (success) or error (failure)
|
|
44
|
+
if (result.ok) {
|
|
45
|
+
return {
|
|
46
|
+
success: true,
|
|
47
|
+
data: result.data,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
return {
|
|
52
|
+
success: false,
|
|
53
|
+
error: `${result.error?.code}: ${result.error?.message}`,
|
|
54
|
+
data: result.partial_data,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
39
58
|
}
|
|
40
59
|
catch (e) {
|
|
41
60
|
return {
|
package/dist/modules/loader.js
CHANGED
|
@@ -57,9 +57,11 @@ async function loadModuleV2(modulePath) {
|
|
|
57
57
|
responsibility: manifest.responsibility || '',
|
|
58
58
|
excludes: manifest.excludes || [],
|
|
59
59
|
constraints: manifest.constraints,
|
|
60
|
+
policies: manifest.policies,
|
|
60
61
|
tools: manifest.tools,
|
|
61
62
|
output: manifest.output,
|
|
62
63
|
failure: manifest.failure,
|
|
64
|
+
runtimeRequirements: manifest.runtime_requirements,
|
|
63
65
|
context: manifest.context,
|
|
64
66
|
prompt,
|
|
65
67
|
inputSchema,
|
package/dist/modules/runner.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Module Runner - Execute Cognitive Modules
|
|
3
|
-
* v2:
|
|
3
|
+
* v2.1: Envelope format support, clean input mapping
|
|
4
4
|
*/
|
|
5
5
|
import type { Provider, CognitiveModule, ModuleResult, ModuleInput } from '../types.js';
|
|
6
6
|
export interface RunOptions {
|
|
7
7
|
input?: ModuleInput;
|
|
8
8
|
args?: string;
|
|
9
9
|
verbose?: boolean;
|
|
10
|
+
useEnvelope?: boolean;
|
|
10
11
|
}
|
|
11
12
|
export declare function runModule(module: CognitiveModule, provider: Provider, options?: RunOptions): Promise<ModuleResult>;
|
package/dist/modules/runner.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Module Runner - Execute Cognitive Modules
|
|
3
|
-
* v2:
|
|
3
|
+
* v2.1: Envelope format support, clean input mapping
|
|
4
4
|
*/
|
|
5
5
|
export async function runModule(module, provider, options = {}) {
|
|
6
|
-
const { args, input, verbose = false } = options;
|
|
6
|
+
const { args, input, verbose = false, useEnvelope } = options;
|
|
7
|
+
// Determine if we should use envelope format
|
|
8
|
+
const shouldUseEnvelope = useEnvelope ?? (module.output?.envelope === true || module.format === 'v2');
|
|
7
9
|
// Build clean input data (v2 style: no $ARGUMENTS pollution)
|
|
8
10
|
const inputData = input || {};
|
|
9
11
|
// Map legacy --args to clean input
|
|
@@ -22,6 +24,7 @@ export async function runModule(module, provider, options = {}) {
|
|
|
22
24
|
console.error('--- Module ---');
|
|
23
25
|
console.error(`Name: ${module.name} (${module.format})`);
|
|
24
26
|
console.error(`Responsibility: ${module.responsibility}`);
|
|
27
|
+
console.error(`Envelope: ${shouldUseEnvelope}`);
|
|
25
28
|
console.error('--- Input ---');
|
|
26
29
|
console.error(JSON.stringify(inputData, null, 2));
|
|
27
30
|
console.error('--- Prompt ---');
|
|
@@ -53,12 +56,27 @@ export async function runModule(module, provider, options = {}) {
|
|
|
53
56
|
systemParts.push('', 'BEHAVIOR EQUIVALENCE:');
|
|
54
57
|
systemParts.push('- You MUST set behavior_equivalence=true ONLY if the output is functionally identical');
|
|
55
58
|
systemParts.push('- If unsure, set behavior_equivalence=false and explain in rationale');
|
|
59
|
+
const maxConfidence = module.constraints?.behavior_equivalence_false_max_confidence ?? 0.7;
|
|
60
|
+
systemParts.push(`- If behavior_equivalence=false, confidence MUST be <= ${maxConfidence}`);
|
|
56
61
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
systemParts.push('-
|
|
62
|
+
// Add envelope format instructions
|
|
63
|
+
if (shouldUseEnvelope) {
|
|
64
|
+
systemParts.push('', 'RESPONSE FORMAT (Envelope):');
|
|
65
|
+
systemParts.push('- Wrap your response in the envelope format');
|
|
66
|
+
systemParts.push('- Success: { "ok": true, "data": { ...your output... } }');
|
|
67
|
+
systemParts.push('- Error: { "ok": false, "error": { "code": "ERROR_CODE", "message": "..." } }');
|
|
68
|
+
systemParts.push('- Include "confidence" (0-1) and "rationale" in data');
|
|
69
|
+
if (module.output?.require_behavior_equivalence) {
|
|
70
|
+
systemParts.push('- Include "behavior_equivalence" (boolean) in data');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
systemParts.push('', 'OUTPUT FORMAT:');
|
|
75
|
+
systemParts.push('- Respond with ONLY valid JSON');
|
|
76
|
+
systemParts.push('- Include "confidence" (0-1) and "rationale" fields');
|
|
77
|
+
if (module.output?.require_behavior_equivalence) {
|
|
78
|
+
systemParts.push('- Include "behavior_equivalence" (boolean) field');
|
|
79
|
+
}
|
|
62
80
|
}
|
|
63
81
|
const messages = [
|
|
64
82
|
{ role: 'system', content: systemParts.join('\n') },
|
|
@@ -76,28 +94,90 @@ export async function runModule(module, provider, options = {}) {
|
|
|
76
94
|
console.error('--- End Response ---');
|
|
77
95
|
}
|
|
78
96
|
// Parse response
|
|
79
|
-
let
|
|
97
|
+
let parsed;
|
|
80
98
|
try {
|
|
81
99
|
const jsonMatch = result.content.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
|
|
82
100
|
const jsonStr = jsonMatch ? jsonMatch[1] : result.content;
|
|
83
|
-
|
|
101
|
+
parsed = JSON.parse(jsonStr.trim());
|
|
84
102
|
}
|
|
85
103
|
catch {
|
|
86
104
|
throw new Error(`Failed to parse JSON response: ${result.content.substring(0, 500)}`);
|
|
87
105
|
}
|
|
88
|
-
//
|
|
106
|
+
// Handle envelope format
|
|
107
|
+
if (shouldUseEnvelope && isEnvelopeResponse(parsed)) {
|
|
108
|
+
return parseEnvelopeResponse(parsed, result.content);
|
|
109
|
+
}
|
|
110
|
+
// Handle legacy format (non-envelope)
|
|
111
|
+
return parseLegacyResponse(parsed, result.content);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if response is in envelope format
|
|
115
|
+
*/
|
|
116
|
+
function isEnvelopeResponse(obj) {
|
|
117
|
+
if (typeof obj !== 'object' || obj === null)
|
|
118
|
+
return false;
|
|
119
|
+
const o = obj;
|
|
120
|
+
return typeof o.ok === 'boolean';
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Parse envelope format response
|
|
124
|
+
*/
|
|
125
|
+
function parseEnvelopeResponse(response, raw) {
|
|
126
|
+
if (response.ok) {
|
|
127
|
+
const data = response.data;
|
|
128
|
+
return {
|
|
129
|
+
ok: true,
|
|
130
|
+
data: {
|
|
131
|
+
...data,
|
|
132
|
+
confidence: typeof data.confidence === 'number' ? data.confidence : 0.5,
|
|
133
|
+
rationale: typeof data.rationale === 'string' ? data.rationale : '',
|
|
134
|
+
behavior_equivalence: data.behavior_equivalence,
|
|
135
|
+
},
|
|
136
|
+
raw,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
return {
|
|
141
|
+
ok: false,
|
|
142
|
+
error: response.error,
|
|
143
|
+
partial_data: response.partial_data,
|
|
144
|
+
raw,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Parse legacy (non-envelope) format response
|
|
150
|
+
*/
|
|
151
|
+
function parseLegacyResponse(output, raw) {
|
|
89
152
|
const outputObj = output;
|
|
90
153
|
const confidence = typeof outputObj.confidence === 'number' ? outputObj.confidence : 0.5;
|
|
91
154
|
const rationale = typeof outputObj.rationale === 'string' ? outputObj.rationale : '';
|
|
92
155
|
const behaviorEquivalence = typeof outputObj.behavior_equivalence === 'boolean'
|
|
93
156
|
? outputObj.behavior_equivalence
|
|
94
157
|
: undefined;
|
|
158
|
+
// Check if this is an error response (has error.code)
|
|
159
|
+
if (outputObj.error && typeof outputObj.error === 'object') {
|
|
160
|
+
const errorObj = outputObj.error;
|
|
161
|
+
if (typeof errorObj.code === 'string') {
|
|
162
|
+
return {
|
|
163
|
+
ok: false,
|
|
164
|
+
error: {
|
|
165
|
+
code: errorObj.code,
|
|
166
|
+
message: typeof errorObj.message === 'string' ? errorObj.message : 'Unknown error',
|
|
167
|
+
},
|
|
168
|
+
raw,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
95
172
|
return {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
173
|
+
ok: true,
|
|
174
|
+
data: {
|
|
175
|
+
...outputObj,
|
|
176
|
+
confidence,
|
|
177
|
+
rationale,
|
|
178
|
+
behavior_equivalence: behaviorEquivalence,
|
|
179
|
+
},
|
|
180
|
+
raw,
|
|
101
181
|
};
|
|
102
182
|
}
|
|
103
183
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cognitive Runtime - Core Types
|
|
3
|
-
* Version 2.
|
|
3
|
+
* Version 2.1 - With envelope format, tools policy, failure contract
|
|
4
4
|
*/
|
|
5
5
|
export interface Provider {
|
|
6
6
|
name: string;
|
|
@@ -31,9 +31,11 @@ export interface CognitiveModule {
|
|
|
31
31
|
responsibility: string;
|
|
32
32
|
excludes: string[];
|
|
33
33
|
constraints?: ModuleConstraints;
|
|
34
|
+
policies?: ModulePolicies;
|
|
34
35
|
tools?: ToolsPolicy;
|
|
35
36
|
output?: OutputContract;
|
|
36
37
|
failure?: FailureContract;
|
|
38
|
+
runtimeRequirements?: RuntimeRequirements;
|
|
37
39
|
context?: 'fork' | 'main';
|
|
38
40
|
prompt: string;
|
|
39
41
|
inputSchema?: object;
|
|
@@ -47,20 +49,68 @@ export interface ModuleConstraints {
|
|
|
47
49
|
no_side_effects?: boolean;
|
|
48
50
|
no_file_write?: boolean;
|
|
49
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';
|
|
50
59
|
}
|
|
51
60
|
export interface ToolsPolicy {
|
|
61
|
+
policy?: 'allow_by_default' | 'deny_by_default';
|
|
52
62
|
allowed: string[];
|
|
63
|
+
denied?: string[];
|
|
53
64
|
}
|
|
54
65
|
export interface OutputContract {
|
|
55
|
-
|
|
66
|
+
format?: 'json_strict' | 'json_lenient' | 'text';
|
|
67
|
+
envelope?: boolean;
|
|
68
|
+
require?: string[];
|
|
56
69
|
require_confidence?: boolean;
|
|
57
70
|
require_rationale?: boolean;
|
|
58
71
|
require_behavior_equivalence?: boolean;
|
|
59
72
|
}
|
|
60
73
|
export interface FailureContract {
|
|
74
|
+
contract?: 'error_union' | 'throw';
|
|
75
|
+
partial_allowed?: boolean;
|
|
76
|
+
must_return_error_schema?: boolean;
|
|
61
77
|
schema?: object;
|
|
62
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;
|
|
102
|
+
}
|
|
63
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 {
|
|
64
114
|
output: unknown;
|
|
65
115
|
confidence: number;
|
|
66
116
|
rationale: string;
|
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
|
@@ -54,16 +54,20 @@ export async function pipe(
|
|
|
54
54
|
input: inputData,
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
// Output
|
|
58
|
-
console.log(JSON.stringify(result
|
|
57
|
+
// Output envelope format to stdout
|
|
58
|
+
console.log(JSON.stringify(result));
|
|
59
59
|
|
|
60
60
|
return {
|
|
61
|
-
success:
|
|
61
|
+
success: result.ok,
|
|
62
62
|
data: result,
|
|
63
63
|
};
|
|
64
64
|
} catch (e) {
|
|
65
65
|
const error = e instanceof Error ? e.message : String(e);
|
|
66
|
-
|
|
66
|
+
// Output error in envelope format
|
|
67
|
+
console.log(JSON.stringify({
|
|
68
|
+
ok: false,
|
|
69
|
+
error: { code: 'RUNTIME_ERROR', message: error }
|
|
70
|
+
}));
|
|
67
71
|
return {
|
|
68
72
|
success: false,
|
|
69
73
|
error,
|
package/src/commands/run.ts
CHANGED
|
@@ -50,10 +50,27 @@ export async function run(
|
|
|
50
50
|
verbose: options.verbose || ctx.verbose,
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
+
}
|
|
57
74
|
} catch (e) {
|
|
58
75
|
return {
|
|
59
76
|
success: false,
|
package/src/modules/loader.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import * as fs from 'node:fs/promises';
|
|
7
7
|
import * as path from 'node:path';
|
|
8
8
|
import yaml from 'js-yaml';
|
|
9
|
-
import type { CognitiveModule, ModuleConstraints, ToolsPolicy, OutputContract, FailureContract } from '../types.js';
|
|
9
|
+
import type { CognitiveModule, ModuleConstraints, ModulePolicies, ToolsPolicy, OutputContract, FailureContract, RuntimeRequirements } from '../types.js';
|
|
10
10
|
|
|
11
11
|
const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n([\s\S]*))?/;
|
|
12
12
|
|
|
@@ -64,9 +64,11 @@ async function loadModuleV2(modulePath: string): Promise<CognitiveModule> {
|
|
|
64
64
|
responsibility: manifest.responsibility as string || '',
|
|
65
65
|
excludes: (manifest.excludes as string[]) || [],
|
|
66
66
|
constraints: manifest.constraints as ModuleConstraints | undefined,
|
|
67
|
+
policies: manifest.policies as ModulePolicies | undefined,
|
|
67
68
|
tools: manifest.tools as ToolsPolicy | undefined,
|
|
68
69
|
output: manifest.output as OutputContract | undefined,
|
|
69
70
|
failure: manifest.failure as FailureContract | undefined,
|
|
71
|
+
runtimeRequirements: manifest.runtime_requirements as RuntimeRequirements | undefined,
|
|
70
72
|
context: manifest.context as 'fork' | 'main' | undefined,
|
|
71
73
|
prompt,
|
|
72
74
|
inputSchema,
|
package/src/modules/runner.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Module Runner - Execute Cognitive Modules
|
|
3
|
-
* v2:
|
|
3
|
+
* v2.1: Envelope format support, clean input mapping
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type {
|
|
6
|
+
import type {
|
|
7
|
+
Provider,
|
|
8
|
+
CognitiveModule,
|
|
9
|
+
ModuleResult,
|
|
10
|
+
Message,
|
|
11
|
+
ModuleInput,
|
|
12
|
+
EnvelopeResponse,
|
|
13
|
+
ModuleResultData
|
|
14
|
+
} from '../types.js';
|
|
7
15
|
|
|
8
16
|
export interface RunOptions {
|
|
9
17
|
// Clean input (v2 style)
|
|
@@ -14,6 +22,9 @@ export interface RunOptions {
|
|
|
14
22
|
|
|
15
23
|
// Runtime options
|
|
16
24
|
verbose?: boolean;
|
|
25
|
+
|
|
26
|
+
// Force envelope format (default: auto-detect from module.output.envelope)
|
|
27
|
+
useEnvelope?: boolean;
|
|
17
28
|
}
|
|
18
29
|
|
|
19
30
|
export async function runModule(
|
|
@@ -21,7 +32,10 @@ export async function runModule(
|
|
|
21
32
|
provider: Provider,
|
|
22
33
|
options: RunOptions = {}
|
|
23
34
|
): Promise<ModuleResult> {
|
|
24
|
-
const { args, input, verbose = false } = options;
|
|
35
|
+
const { args, input, verbose = false, useEnvelope } = options;
|
|
36
|
+
|
|
37
|
+
// Determine if we should use envelope format
|
|
38
|
+
const shouldUseEnvelope = useEnvelope ?? (module.output?.envelope === true || module.format === 'v2');
|
|
25
39
|
|
|
26
40
|
// Build clean input data (v2 style: no $ARGUMENTS pollution)
|
|
27
41
|
const inputData: ModuleInput = input || {};
|
|
@@ -43,6 +57,7 @@ export async function runModule(
|
|
|
43
57
|
console.error('--- Module ---');
|
|
44
58
|
console.error(`Name: ${module.name} (${module.format})`);
|
|
45
59
|
console.error(`Responsibility: ${module.responsibility}`);
|
|
60
|
+
console.error(`Envelope: ${shouldUseEnvelope}`);
|
|
46
61
|
console.error('--- Input ---');
|
|
47
62
|
console.error(JSON.stringify(inputData, null, 2));
|
|
48
63
|
console.error('--- Prompt ---');
|
|
@@ -74,13 +89,28 @@ export async function runModule(
|
|
|
74
89
|
systemParts.push('', 'BEHAVIOR EQUIVALENCE:');
|
|
75
90
|
systemParts.push('- You MUST set behavior_equivalence=true ONLY if the output is functionally identical');
|
|
76
91
|
systemParts.push('- If unsure, set behavior_equivalence=false and explain in rationale');
|
|
92
|
+
|
|
93
|
+
const maxConfidence = module.constraints?.behavior_equivalence_false_max_confidence ?? 0.7;
|
|
94
|
+
systemParts.push(`- If behavior_equivalence=false, confidence MUST be <= ${maxConfidence}`);
|
|
77
95
|
}
|
|
78
96
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
systemParts.push('-
|
|
97
|
+
// Add envelope format instructions
|
|
98
|
+
if (shouldUseEnvelope) {
|
|
99
|
+
systemParts.push('', 'RESPONSE FORMAT (Envelope):');
|
|
100
|
+
systemParts.push('- Wrap your response in the envelope format');
|
|
101
|
+
systemParts.push('- Success: { "ok": true, "data": { ...your output... } }');
|
|
102
|
+
systemParts.push('- Error: { "ok": false, "error": { "code": "ERROR_CODE", "message": "..." } }');
|
|
103
|
+
systemParts.push('- Include "confidence" (0-1) and "rationale" in data');
|
|
104
|
+
if (module.output?.require_behavior_equivalence) {
|
|
105
|
+
systemParts.push('- Include "behavior_equivalence" (boolean) in data');
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
systemParts.push('', 'OUTPUT FORMAT:');
|
|
109
|
+
systemParts.push('- Respond with ONLY valid JSON');
|
|
110
|
+
systemParts.push('- Include "confidence" (0-1) and "rationale" fields');
|
|
111
|
+
if (module.output?.require_behavior_equivalence) {
|
|
112
|
+
systemParts.push('- Include "behavior_equivalence" (boolean) field');
|
|
113
|
+
}
|
|
84
114
|
}
|
|
85
115
|
|
|
86
116
|
const messages: Message[] = [
|
|
@@ -102,16 +132,63 @@ export async function runModule(
|
|
|
102
132
|
}
|
|
103
133
|
|
|
104
134
|
// Parse response
|
|
105
|
-
let
|
|
135
|
+
let parsed: unknown;
|
|
106
136
|
try {
|
|
107
137
|
const jsonMatch = result.content.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
|
|
108
138
|
const jsonStr = jsonMatch ? jsonMatch[1] : result.content;
|
|
109
|
-
|
|
139
|
+
parsed = JSON.parse(jsonStr.trim());
|
|
110
140
|
} catch {
|
|
111
141
|
throw new Error(`Failed to parse JSON response: ${result.content.substring(0, 500)}`);
|
|
112
142
|
}
|
|
113
143
|
|
|
114
|
-
//
|
|
144
|
+
// Handle envelope format
|
|
145
|
+
if (shouldUseEnvelope && isEnvelopeResponse(parsed)) {
|
|
146
|
+
return parseEnvelopeResponse(parsed, result.content);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Handle legacy format (non-envelope)
|
|
150
|
+
return parseLegacyResponse(parsed, result.content);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Check if response is in envelope format
|
|
155
|
+
*/
|
|
156
|
+
function isEnvelopeResponse(obj: unknown): obj is EnvelopeResponse {
|
|
157
|
+
if (typeof obj !== 'object' || obj === null) return false;
|
|
158
|
+
const o = obj as Record<string, unknown>;
|
|
159
|
+
return typeof o.ok === 'boolean';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Parse envelope format response
|
|
164
|
+
*/
|
|
165
|
+
function parseEnvelopeResponse(response: EnvelopeResponse, raw: string): ModuleResult {
|
|
166
|
+
if (response.ok) {
|
|
167
|
+
const data = response.data as ModuleResultData;
|
|
168
|
+
return {
|
|
169
|
+
ok: true,
|
|
170
|
+
data: {
|
|
171
|
+
...data,
|
|
172
|
+
confidence: typeof data.confidence === 'number' ? data.confidence : 0.5,
|
|
173
|
+
rationale: typeof data.rationale === 'string' ? data.rationale : '',
|
|
174
|
+
behavior_equivalence: data.behavior_equivalence,
|
|
175
|
+
},
|
|
176
|
+
raw,
|
|
177
|
+
};
|
|
178
|
+
} else {
|
|
179
|
+
return {
|
|
180
|
+
ok: false,
|
|
181
|
+
error: response.error,
|
|
182
|
+
partial_data: response.partial_data,
|
|
183
|
+
raw,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Parse legacy (non-envelope) format response
|
|
190
|
+
*/
|
|
191
|
+
function parseLegacyResponse(output: unknown, raw: string): ModuleResult {
|
|
115
192
|
const outputObj = output as Record<string, unknown>;
|
|
116
193
|
const confidence = typeof outputObj.confidence === 'number' ? outputObj.confidence : 0.5;
|
|
117
194
|
const rationale = typeof outputObj.rationale === 'string' ? outputObj.rationale : '';
|
|
@@ -119,12 +196,30 @@ export async function runModule(
|
|
|
119
196
|
? outputObj.behavior_equivalence
|
|
120
197
|
: undefined;
|
|
121
198
|
|
|
199
|
+
// Check if this is an error response (has error.code)
|
|
200
|
+
if (outputObj.error && typeof outputObj.error === 'object') {
|
|
201
|
+
const errorObj = outputObj.error as Record<string, unknown>;
|
|
202
|
+
if (typeof errorObj.code === 'string') {
|
|
203
|
+
return {
|
|
204
|
+
ok: false,
|
|
205
|
+
error: {
|
|
206
|
+
code: errorObj.code,
|
|
207
|
+
message: typeof errorObj.message === 'string' ? errorObj.message : 'Unknown error',
|
|
208
|
+
},
|
|
209
|
+
raw,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
122
214
|
return {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
215
|
+
ok: true,
|
|
216
|
+
data: {
|
|
217
|
+
...outputObj,
|
|
218
|
+
confidence,
|
|
219
|
+
rationale,
|
|
220
|
+
behavior_equivalence: behaviorEquivalence,
|
|
221
|
+
} as ModuleResultData,
|
|
222
|
+
raw,
|
|
128
223
|
};
|
|
129
224
|
}
|
|
130
225
|
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cognitive Runtime - Core Types
|
|
3
|
-
* Version 2.
|
|
3
|
+
* Version 2.1 - With envelope format, tools policy, failure contract
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// Provider interface - all LLM providers implement this
|
|
@@ -31,7 +31,7 @@ export interface InvokeResult {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
// Module types (v2)
|
|
34
|
+
// Module types (v2.1)
|
|
35
35
|
export interface CognitiveModule {
|
|
36
36
|
// Core identity
|
|
37
37
|
name: string;
|
|
@@ -42,6 +42,9 @@ export interface CognitiveModule {
|
|
|
42
42
|
excludes: string[];
|
|
43
43
|
constraints?: ModuleConstraints;
|
|
44
44
|
|
|
45
|
+
// Unified policies (v2.1)
|
|
46
|
+
policies?: ModulePolicies;
|
|
47
|
+
|
|
45
48
|
// Tools policy
|
|
46
49
|
tools?: ToolsPolicy;
|
|
47
50
|
|
|
@@ -51,6 +54,9 @@ export interface CognitiveModule {
|
|
|
51
54
|
// Failure contract
|
|
52
55
|
failure?: FailureContract;
|
|
53
56
|
|
|
57
|
+
// Runtime requirements
|
|
58
|
+
runtimeRequirements?: RuntimeRequirements;
|
|
59
|
+
|
|
54
60
|
// Execution context
|
|
55
61
|
context?: 'fork' | 'main';
|
|
56
62
|
|
|
@@ -72,24 +78,82 @@ export interface ModuleConstraints {
|
|
|
72
78
|
no_side_effects?: boolean;
|
|
73
79
|
no_file_write?: boolean;
|
|
74
80
|
no_inventing_data?: boolean;
|
|
81
|
+
behavior_equivalence_false_max_confidence?: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface ModulePolicies {
|
|
85
|
+
network?: 'allow' | 'deny';
|
|
86
|
+
filesystem_write?: 'allow' | 'deny';
|
|
87
|
+
side_effects?: 'allow' | 'deny';
|
|
88
|
+
code_execution?: 'allow' | 'deny';
|
|
75
89
|
}
|
|
76
90
|
|
|
77
91
|
export interface ToolsPolicy {
|
|
92
|
+
policy?: 'allow_by_default' | 'deny_by_default';
|
|
78
93
|
allowed: string[];
|
|
94
|
+
denied?: string[];
|
|
79
95
|
}
|
|
80
96
|
|
|
81
97
|
export interface OutputContract {
|
|
82
|
-
|
|
98
|
+
format?: 'json_strict' | 'json_lenient' | 'text';
|
|
99
|
+
envelope?: boolean; // v2.1: Use {ok, data/error} wrapper
|
|
100
|
+
require?: string[];
|
|
83
101
|
require_confidence?: boolean;
|
|
84
102
|
require_rationale?: boolean;
|
|
85
103
|
require_behavior_equivalence?: boolean;
|
|
86
104
|
}
|
|
87
105
|
|
|
88
106
|
export interface FailureContract {
|
|
107
|
+
contract?: 'error_union' | 'throw';
|
|
108
|
+
partial_allowed?: boolean;
|
|
109
|
+
must_return_error_schema?: boolean;
|
|
89
110
|
schema?: object;
|
|
90
111
|
}
|
|
91
112
|
|
|
113
|
+
export interface RuntimeRequirements {
|
|
114
|
+
structured_output?: boolean;
|
|
115
|
+
max_input_tokens?: number;
|
|
116
|
+
preferred_capabilities?: string[];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Envelope response format (v2.1)
|
|
120
|
+
export interface EnvelopeSuccess<T = unknown> {
|
|
121
|
+
ok: true;
|
|
122
|
+
data: T;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface EnvelopeError {
|
|
126
|
+
ok: false;
|
|
127
|
+
error: {
|
|
128
|
+
code: string;
|
|
129
|
+
message: string;
|
|
130
|
+
};
|
|
131
|
+
partial_data?: unknown;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export type EnvelopeResponse<T = unknown> = EnvelopeSuccess<T> | EnvelopeError;
|
|
135
|
+
|
|
136
|
+
// Module result types
|
|
137
|
+
export interface ModuleResultData {
|
|
138
|
+
[key: string]: unknown;
|
|
139
|
+
confidence: number;
|
|
140
|
+
rationale: string;
|
|
141
|
+
behavior_equivalence?: boolean;
|
|
142
|
+
}
|
|
143
|
+
|
|
92
144
|
export interface ModuleResult {
|
|
145
|
+
ok: boolean;
|
|
146
|
+
data?: ModuleResultData;
|
|
147
|
+
error?: {
|
|
148
|
+
code: string;
|
|
149
|
+
message: string;
|
|
150
|
+
};
|
|
151
|
+
partial_data?: unknown;
|
|
152
|
+
raw?: string;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Legacy result format (for backward compatibility)
|
|
156
|
+
export interface LegacyModuleResult {
|
|
93
157
|
output: unknown;
|
|
94
158
|
confidence: number;
|
|
95
159
|
rationale: string;
|