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/src/modules/index.ts
DELETED
package/src/modules/loader.ts
DELETED
|
@@ -1,508 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Module Loader - Load and parse Cognitive Modules
|
|
3
|
-
* Supports v0 (6-file), v1 (MODULE.md) and v2 (module.yaml + prompt.md) formats
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as fs from 'node:fs/promises';
|
|
7
|
-
import * as path from 'node:path';
|
|
8
|
-
import yaml from 'js-yaml';
|
|
9
|
-
import type {
|
|
10
|
-
CognitiveModule,
|
|
11
|
-
ModuleConstraints,
|
|
12
|
-
ModulePolicies,
|
|
13
|
-
ToolsPolicy,
|
|
14
|
-
OutputContract,
|
|
15
|
-
FailureContract,
|
|
16
|
-
RuntimeRequirements,
|
|
17
|
-
OverflowConfig,
|
|
18
|
-
EnumConfig,
|
|
19
|
-
CompatConfig,
|
|
20
|
-
MetaConfig,
|
|
21
|
-
ModuleTier,
|
|
22
|
-
SchemaStrictness,
|
|
23
|
-
CompositionConfig,
|
|
24
|
-
CompositionPattern,
|
|
25
|
-
DependencyDeclaration,
|
|
26
|
-
DataflowStep,
|
|
27
|
-
RoutingRule,
|
|
28
|
-
AggregationStrategy,
|
|
29
|
-
IterationConfig
|
|
30
|
-
} from '../types.js';
|
|
31
|
-
|
|
32
|
-
const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n([\s\S]*))?/;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Detect module format version
|
|
36
|
-
*/
|
|
37
|
-
async function detectFormat(modulePath: string): Promise<'v0' | 'v1' | 'v2'> {
|
|
38
|
-
const v2Manifest = path.join(modulePath, 'module.yaml');
|
|
39
|
-
const v1Module = path.join(modulePath, 'MODULE.md');
|
|
40
|
-
const v0Module = path.join(modulePath, 'module.md');
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
await fs.access(v2Manifest);
|
|
44
|
-
return 'v2';
|
|
45
|
-
} catch {
|
|
46
|
-
try {
|
|
47
|
-
await fs.access(v1Module);
|
|
48
|
-
return 'v1';
|
|
49
|
-
} catch {
|
|
50
|
-
try {
|
|
51
|
-
await fs.access(v0Module);
|
|
52
|
-
return 'v0';
|
|
53
|
-
} catch {
|
|
54
|
-
throw new Error(`No module.yaml, MODULE.md, or module.md found in ${modulePath}`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Detect v2.x sub-version from manifest
|
|
62
|
-
*/
|
|
63
|
-
function detectV2Version(manifest: Record<string, unknown>): string {
|
|
64
|
-
if (manifest.tier || manifest.overflow || manifest.enums) {
|
|
65
|
-
return 'v2.2';
|
|
66
|
-
}
|
|
67
|
-
if (manifest.policies || manifest.failure) {
|
|
68
|
-
return 'v2.1';
|
|
69
|
-
}
|
|
70
|
-
return 'v2.0';
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Load v2 format module (module.yaml + prompt.md)
|
|
75
|
-
*/
|
|
76
|
-
async function loadModuleV2(modulePath: string): Promise<CognitiveModule> {
|
|
77
|
-
const manifestFile = path.join(modulePath, 'module.yaml');
|
|
78
|
-
const promptFile = path.join(modulePath, 'prompt.md');
|
|
79
|
-
const schemaFile = path.join(modulePath, 'schema.json');
|
|
80
|
-
|
|
81
|
-
// Read module.yaml
|
|
82
|
-
const manifestContent = await fs.readFile(manifestFile, 'utf-8');
|
|
83
|
-
const manifest = yaml.load(manifestContent) as Record<string, unknown>;
|
|
84
|
-
|
|
85
|
-
// Detect v2.x version
|
|
86
|
-
const formatVersion = detectV2Version(manifest);
|
|
87
|
-
|
|
88
|
-
// Read prompt.md
|
|
89
|
-
let prompt = '';
|
|
90
|
-
try {
|
|
91
|
-
prompt = await fs.readFile(promptFile, 'utf-8');
|
|
92
|
-
} catch {
|
|
93
|
-
// prompt.md is optional, manifest may include inline prompt
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Read schema.json
|
|
97
|
-
let inputSchema: object | undefined;
|
|
98
|
-
let outputSchema: object | undefined;
|
|
99
|
-
let dataSchema: object | undefined;
|
|
100
|
-
let metaSchema: object | undefined;
|
|
101
|
-
let errorSchema: object | undefined;
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
const schemaContent = await fs.readFile(schemaFile, 'utf-8');
|
|
105
|
-
const schema = JSON.parse(schemaContent);
|
|
106
|
-
inputSchema = schema.input;
|
|
107
|
-
// Support both "data" (v2.2) and "output" (v2.1) aliases
|
|
108
|
-
dataSchema = schema.data || schema.output;
|
|
109
|
-
outputSchema = dataSchema; // Backward compat
|
|
110
|
-
metaSchema = schema.meta;
|
|
111
|
-
errorSchema = schema.error;
|
|
112
|
-
} catch {
|
|
113
|
-
// Schema file is optional but recommended
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Extract v2.2 fields
|
|
117
|
-
const tier = manifest.tier as ModuleTier | undefined;
|
|
118
|
-
const schemaStrictness = (manifest.schema_strictness as SchemaStrictness) || 'medium';
|
|
119
|
-
|
|
120
|
-
// Determine default max_items based on strictness (SPEC-v2.2)
|
|
121
|
-
const strictnessMaxItems: Record<SchemaStrictness, number> = {
|
|
122
|
-
high: 0,
|
|
123
|
-
medium: 5,
|
|
124
|
-
low: 20
|
|
125
|
-
};
|
|
126
|
-
const defaultMaxItems = strictnessMaxItems[schemaStrictness] ?? 5;
|
|
127
|
-
const defaultEnabled = schemaStrictness !== 'high';
|
|
128
|
-
|
|
129
|
-
// Parse overflow config with strictness-based defaults
|
|
130
|
-
const overflowRaw = (manifest.overflow as Record<string, unknown>) || {};
|
|
131
|
-
const overflow: OverflowConfig = {
|
|
132
|
-
enabled: (overflowRaw.enabled as boolean) ?? defaultEnabled,
|
|
133
|
-
recoverable: (overflowRaw.recoverable as boolean) ?? true,
|
|
134
|
-
max_items: (overflowRaw.max_items as number) ?? defaultMaxItems,
|
|
135
|
-
require_suggested_mapping: (overflowRaw.require_suggested_mapping as boolean) ?? true
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
// Parse enums config
|
|
139
|
-
const enumsRaw = (manifest.enums as Record<string, unknown>) || {};
|
|
140
|
-
const enums: EnumConfig = {
|
|
141
|
-
strategy: (enumsRaw.strategy as 'strict' | 'extensible') ??
|
|
142
|
-
(tier === 'exec' ? 'strict' : 'extensible'),
|
|
143
|
-
unknown_tag: (enumsRaw.unknown_tag as string) ?? 'custom'
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
// Parse compat config
|
|
147
|
-
const compatRaw = (manifest.compat as Record<string, unknown>) || {};
|
|
148
|
-
const compat: CompatConfig = {
|
|
149
|
-
accepts_v21_payload: (compatRaw.accepts_v21_payload as boolean) ?? true,
|
|
150
|
-
runtime_auto_wrap: (compatRaw.runtime_auto_wrap as boolean) ?? true,
|
|
151
|
-
schema_output_alias: (compatRaw.schema_output_alias as 'data' | 'output') ?? 'data'
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
// Parse meta config (including risk_rule) with validation
|
|
155
|
-
const metaRaw = (manifest.meta as Record<string, unknown>) || {};
|
|
156
|
-
const rawRiskRule = metaRaw.risk_rule as string | undefined;
|
|
157
|
-
const validRiskRules = ['max_changes_risk', 'max_issues_risk', 'explicit'];
|
|
158
|
-
const validatedRiskRule = rawRiskRule && validRiskRules.includes(rawRiskRule)
|
|
159
|
-
? rawRiskRule as 'max_changes_risk' | 'max_issues_risk' | 'explicit'
|
|
160
|
-
: undefined;
|
|
161
|
-
|
|
162
|
-
const metaConfig: MetaConfig = {
|
|
163
|
-
required: metaRaw.required as string[] | undefined,
|
|
164
|
-
risk_rule: validatedRiskRule,
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
// Parse composition config (v2.2)
|
|
168
|
-
const compositionRaw = manifest.composition as Record<string, unknown> | undefined;
|
|
169
|
-
let composition: CompositionConfig | undefined;
|
|
170
|
-
|
|
171
|
-
if (compositionRaw) {
|
|
172
|
-
// Parse pattern
|
|
173
|
-
const pattern = compositionRaw.pattern as CompositionPattern ?? 'sequential';
|
|
174
|
-
|
|
175
|
-
// Parse requires (dependencies)
|
|
176
|
-
const requiresRaw = compositionRaw.requires as Array<Record<string, unknown>> | undefined;
|
|
177
|
-
const requires: DependencyDeclaration[] | undefined = requiresRaw?.map(dep => ({
|
|
178
|
-
name: dep.name as string,
|
|
179
|
-
version: dep.version as string | undefined,
|
|
180
|
-
optional: dep.optional as boolean | undefined,
|
|
181
|
-
fallback: dep.fallback as string | null | undefined,
|
|
182
|
-
timeout_ms: dep.timeout_ms as number | undefined
|
|
183
|
-
}));
|
|
184
|
-
|
|
185
|
-
// Parse dataflow
|
|
186
|
-
const dataflowRaw = compositionRaw.dataflow as Array<Record<string, unknown>> | undefined;
|
|
187
|
-
const dataflow: DataflowStep[] | undefined = dataflowRaw?.map(step => ({
|
|
188
|
-
from: step.from as string | string[],
|
|
189
|
-
to: step.to as string | string[],
|
|
190
|
-
mapping: step.mapping as Record<string, string> | undefined,
|
|
191
|
-
condition: step.condition as string | undefined,
|
|
192
|
-
aggregate: step.aggregate as AggregationStrategy | undefined,
|
|
193
|
-
aggregator: step.aggregator as string | undefined
|
|
194
|
-
}));
|
|
195
|
-
|
|
196
|
-
// Parse routing rules
|
|
197
|
-
const routingRaw = compositionRaw.routing as Array<Record<string, unknown>> | undefined;
|
|
198
|
-
const routing: RoutingRule[] | undefined = routingRaw?.map(rule => ({
|
|
199
|
-
condition: rule.condition as string,
|
|
200
|
-
next: rule.next as string | null
|
|
201
|
-
}));
|
|
202
|
-
|
|
203
|
-
// Parse iteration config
|
|
204
|
-
const iterationRaw = compositionRaw.iteration as Record<string, unknown> | undefined;
|
|
205
|
-
const iteration: IterationConfig | undefined = iterationRaw ? {
|
|
206
|
-
max_iterations: iterationRaw.max_iterations as number | undefined,
|
|
207
|
-
continue_condition: iterationRaw.continue_condition as string | undefined,
|
|
208
|
-
stop_condition: iterationRaw.stop_condition as string | undefined
|
|
209
|
-
} : undefined;
|
|
210
|
-
|
|
211
|
-
composition = {
|
|
212
|
-
pattern,
|
|
213
|
-
requires,
|
|
214
|
-
dataflow,
|
|
215
|
-
routing,
|
|
216
|
-
max_depth: compositionRaw.max_depth as number | undefined,
|
|
217
|
-
timeout_ms: compositionRaw.timeout_ms as number | undefined,
|
|
218
|
-
iteration
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return {
|
|
223
|
-
name: manifest.name as string || path.basename(modulePath),
|
|
224
|
-
version: manifest.version as string || '1.0.0',
|
|
225
|
-
responsibility: manifest.responsibility as string || '',
|
|
226
|
-
excludes: (manifest.excludes as string[]) || [],
|
|
227
|
-
constraints: manifest.constraints as ModuleConstraints | undefined,
|
|
228
|
-
policies: manifest.policies as ModulePolicies | undefined,
|
|
229
|
-
tools: manifest.tools as ToolsPolicy | undefined,
|
|
230
|
-
output: manifest.output as OutputContract | undefined,
|
|
231
|
-
failure: manifest.failure as FailureContract | undefined,
|
|
232
|
-
runtimeRequirements: manifest.runtime_requirements as RuntimeRequirements | undefined,
|
|
233
|
-
// v2.2 fields
|
|
234
|
-
tier,
|
|
235
|
-
schemaStrictness,
|
|
236
|
-
overflow,
|
|
237
|
-
enums,
|
|
238
|
-
compat,
|
|
239
|
-
metaConfig,
|
|
240
|
-
composition,
|
|
241
|
-
// Context and prompt
|
|
242
|
-
context: manifest.context as 'fork' | 'main' | undefined,
|
|
243
|
-
prompt,
|
|
244
|
-
// Schemas
|
|
245
|
-
inputSchema,
|
|
246
|
-
outputSchema,
|
|
247
|
-
dataSchema,
|
|
248
|
-
metaSchema,
|
|
249
|
-
errorSchema,
|
|
250
|
-
// Metadata
|
|
251
|
-
location: modulePath,
|
|
252
|
-
format: 'v2',
|
|
253
|
-
formatVersion,
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Load v1 format module (MODULE.md with frontmatter)
|
|
259
|
-
*/
|
|
260
|
-
async function loadModuleV1(modulePath: string): Promise<CognitiveModule> {
|
|
261
|
-
const moduleFile = path.join(modulePath, 'MODULE.md');
|
|
262
|
-
const schemaFile = path.join(modulePath, 'schema.json');
|
|
263
|
-
|
|
264
|
-
// Read MODULE.md
|
|
265
|
-
const moduleContent = await fs.readFile(moduleFile, 'utf-8');
|
|
266
|
-
|
|
267
|
-
// Parse frontmatter
|
|
268
|
-
const match = moduleContent.match(FRONTMATTER_REGEX);
|
|
269
|
-
if (!match) {
|
|
270
|
-
throw new Error(`Invalid MODULE.md: missing YAML frontmatter in ${moduleFile}`);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
const frontmatter = yaml.load(match[1]) as Record<string, unknown>;
|
|
274
|
-
const prompt = (match[2] || '').trim();
|
|
275
|
-
|
|
276
|
-
// Read schema.json
|
|
277
|
-
let inputSchema: object | undefined;
|
|
278
|
-
let outputSchema: object | undefined;
|
|
279
|
-
|
|
280
|
-
try {
|
|
281
|
-
const schemaContent = await fs.readFile(schemaFile, 'utf-8');
|
|
282
|
-
const schema = JSON.parse(schemaContent);
|
|
283
|
-
inputSchema = schema.input;
|
|
284
|
-
outputSchema = schema.output;
|
|
285
|
-
} catch {
|
|
286
|
-
// Schema file is optional
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Extract constraints from v1 format
|
|
290
|
-
const constraints: ModuleConstraints = {};
|
|
291
|
-
const v1Constraints = frontmatter.constraints as Record<string, boolean> | undefined;
|
|
292
|
-
if (v1Constraints) {
|
|
293
|
-
constraints.no_network = v1Constraints.no_network;
|
|
294
|
-
constraints.no_side_effects = v1Constraints.no_side_effects;
|
|
295
|
-
constraints.no_inventing_data = v1Constraints.no_inventing_data;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return {
|
|
299
|
-
name: frontmatter.name as string || path.basename(modulePath),
|
|
300
|
-
version: frontmatter.version as string || '1.0.0',
|
|
301
|
-
responsibility: frontmatter.responsibility as string || '',
|
|
302
|
-
excludes: (frontmatter.excludes as string[]) || [],
|
|
303
|
-
constraints: Object.keys(constraints).length > 0 ? constraints : undefined,
|
|
304
|
-
context: frontmatter.context as 'fork' | 'main' | undefined,
|
|
305
|
-
prompt,
|
|
306
|
-
inputSchema,
|
|
307
|
-
outputSchema,
|
|
308
|
-
location: modulePath,
|
|
309
|
-
format: 'v1',
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* Load v0 format module (6-file format - deprecated)
|
|
315
|
-
*/
|
|
316
|
-
async function loadModuleV0(modulePath: string): Promise<CognitiveModule> {
|
|
317
|
-
// Read module.md
|
|
318
|
-
const moduleFile = path.join(modulePath, 'module.md');
|
|
319
|
-
const moduleContent = await fs.readFile(moduleFile, 'utf-8');
|
|
320
|
-
|
|
321
|
-
// Parse frontmatter
|
|
322
|
-
const match = moduleContent.match(FRONTMATTER_REGEX);
|
|
323
|
-
if (!match) {
|
|
324
|
-
throw new Error(`Invalid module.md: missing YAML frontmatter in ${moduleFile}`);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const metadata = yaml.load(match[1]) as Record<string, unknown>;
|
|
328
|
-
|
|
329
|
-
// Read schemas
|
|
330
|
-
const inputSchemaFile = path.join(modulePath, 'input.schema.json');
|
|
331
|
-
const outputSchemaFile = path.join(modulePath, 'output.schema.json');
|
|
332
|
-
const constraintsFile = path.join(modulePath, 'constraints.yaml');
|
|
333
|
-
const promptFile = path.join(modulePath, 'prompt.txt');
|
|
334
|
-
|
|
335
|
-
const inputSchemaContent = await fs.readFile(inputSchemaFile, 'utf-8');
|
|
336
|
-
const inputSchema = JSON.parse(inputSchemaContent);
|
|
337
|
-
|
|
338
|
-
const outputSchemaContent = await fs.readFile(outputSchemaFile, 'utf-8');
|
|
339
|
-
const outputSchema = JSON.parse(outputSchemaContent);
|
|
340
|
-
|
|
341
|
-
// Load constraints
|
|
342
|
-
const constraintsContent = await fs.readFile(constraintsFile, 'utf-8');
|
|
343
|
-
const constraintsRaw = yaml.load(constraintsContent) as Record<string, unknown>;
|
|
344
|
-
|
|
345
|
-
// Load prompt
|
|
346
|
-
const prompt = await fs.readFile(promptFile, 'utf-8');
|
|
347
|
-
|
|
348
|
-
// Extract constraints
|
|
349
|
-
const constraints: ModuleConstraints = {};
|
|
350
|
-
if (constraintsRaw) {
|
|
351
|
-
const operational = (constraintsRaw.operational as Record<string, boolean>) ?? {};
|
|
352
|
-
constraints.no_network = operational.no_external_network;
|
|
353
|
-
constraints.no_side_effects = operational.no_side_effects;
|
|
354
|
-
constraints.no_file_write = operational.no_file_write;
|
|
355
|
-
constraints.no_inventing_data = operational.no_inventing_data;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
return {
|
|
359
|
-
name: metadata.name as string || path.basename(modulePath),
|
|
360
|
-
version: metadata.version as string || '1.0.0',
|
|
361
|
-
responsibility: metadata.responsibility as string || '',
|
|
362
|
-
excludes: (metadata.excludes as string[]) || [],
|
|
363
|
-
constraints: Object.keys(constraints).length > 0 ? constraints : undefined,
|
|
364
|
-
prompt,
|
|
365
|
-
inputSchema,
|
|
366
|
-
outputSchema,
|
|
367
|
-
dataSchema: outputSchema, // Alias for v2.2 compat
|
|
368
|
-
// v2.2 defaults for v0 modules
|
|
369
|
-
schemaStrictness: 'medium',
|
|
370
|
-
overflow: { enabled: false },
|
|
371
|
-
enums: { strategy: 'strict' },
|
|
372
|
-
compat: { accepts_v21_payload: true, runtime_auto_wrap: true },
|
|
373
|
-
// Metadata
|
|
374
|
-
location: modulePath,
|
|
375
|
-
format: 'v0',
|
|
376
|
-
formatVersion: 'v0.0',
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Load a Cognitive Module (auto-detects format)
|
|
382
|
-
*/
|
|
383
|
-
export async function loadModule(modulePath: string): Promise<CognitiveModule> {
|
|
384
|
-
const format = await detectFormat(modulePath);
|
|
385
|
-
|
|
386
|
-
if (format === 'v2') {
|
|
387
|
-
return loadModuleV2(modulePath);
|
|
388
|
-
} else if (format === 'v1') {
|
|
389
|
-
return loadModuleV1(modulePath);
|
|
390
|
-
} else {
|
|
391
|
-
return loadModuleV0(modulePath);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* Check if a directory contains a valid module
|
|
397
|
-
*/
|
|
398
|
-
async function isValidModule(modulePath: string): Promise<boolean> {
|
|
399
|
-
const v2Manifest = path.join(modulePath, 'module.yaml');
|
|
400
|
-
const v1Module = path.join(modulePath, 'MODULE.md');
|
|
401
|
-
const v0Module = path.join(modulePath, 'module.md');
|
|
402
|
-
|
|
403
|
-
try {
|
|
404
|
-
await fs.access(v2Manifest);
|
|
405
|
-
return true;
|
|
406
|
-
} catch {
|
|
407
|
-
try {
|
|
408
|
-
await fs.access(v1Module);
|
|
409
|
-
return true;
|
|
410
|
-
} catch {
|
|
411
|
-
try {
|
|
412
|
-
await fs.access(v0Module);
|
|
413
|
-
return true;
|
|
414
|
-
} catch {
|
|
415
|
-
return false;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
export async function findModule(name: string, searchPaths: string[]): Promise<CognitiveModule | null> {
|
|
422
|
-
for (const basePath of searchPaths) {
|
|
423
|
-
const modulePath = path.join(basePath, name);
|
|
424
|
-
|
|
425
|
-
if (await isValidModule(modulePath)) {
|
|
426
|
-
return await loadModule(modulePath);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
return null;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
export async function listModules(searchPaths: string[]): Promise<CognitiveModule[]> {
|
|
434
|
-
const modules: CognitiveModule[] = [];
|
|
435
|
-
|
|
436
|
-
for (const basePath of searchPaths) {
|
|
437
|
-
try {
|
|
438
|
-
const entries = await fs.readdir(basePath, { withFileTypes: true });
|
|
439
|
-
|
|
440
|
-
for (const entry of entries) {
|
|
441
|
-
if (entry.isDirectory()) {
|
|
442
|
-
const modulePath = path.join(basePath, entry.name);
|
|
443
|
-
|
|
444
|
-
if (await isValidModule(modulePath)) {
|
|
445
|
-
try {
|
|
446
|
-
const module = await loadModule(modulePath);
|
|
447
|
-
modules.push(module);
|
|
448
|
-
} catch {
|
|
449
|
-
// Skip invalid modules
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
} catch {
|
|
455
|
-
// Path doesn't exist, skip
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
return modules;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
export function getDefaultSearchPaths(cwd: string): string[] {
|
|
463
|
-
const home = process.env.HOME || '';
|
|
464
|
-
return [
|
|
465
|
-
path.join(cwd, 'cognitive', 'modules'),
|
|
466
|
-
path.join(cwd, '.cognitive', 'modules'),
|
|
467
|
-
path.join(home, '.cognitive', 'modules'),
|
|
468
|
-
];
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// =============================================================================
|
|
472
|
-
// Utility Functions
|
|
473
|
-
// =============================================================================
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Get module tier (exec, decision, exploration).
|
|
477
|
-
*/
|
|
478
|
-
export function getModuleTier(module: CognitiveModule): ModuleTier | undefined {
|
|
479
|
-
return module.tier;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* Get schema strictness level.
|
|
484
|
-
*/
|
|
485
|
-
export function getSchemaStrictness(module: CognitiveModule): SchemaStrictness {
|
|
486
|
-
return module.schemaStrictness ?? 'medium';
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
/**
|
|
490
|
-
* Check if overflow (extensions.insights) is enabled.
|
|
491
|
-
*/
|
|
492
|
-
export function isOverflowEnabled(module: CognitiveModule): boolean {
|
|
493
|
-
return module.overflow?.enabled ?? false;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* Get enum extension strategy.
|
|
498
|
-
*/
|
|
499
|
-
export function getEnumStrategy(module: CognitiveModule): 'strict' | 'extensible' {
|
|
500
|
-
return module.enums?.strategy ?? 'strict';
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* Check if runtime should auto-wrap v2.1 to v2.2.
|
|
505
|
-
*/
|
|
506
|
-
export function shouldAutoWrap(module: CognitiveModule): boolean {
|
|
507
|
-
return module.compat?.runtime_auto_wrap ?? true;
|
|
508
|
-
}
|