coaian 0.7.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.
@@ -0,0 +1,28 @@
1
+ type ValidationType = 'string' | 'number' | 'boolean' | 'array' | 'object' | 'date' | 'enum';
2
+ interface ValidationRule {
3
+ type: ValidationType;
4
+ required?: boolean;
5
+ minLength?: number;
6
+ maxLength?: number;
7
+ pattern?: RegExp;
8
+ minValue?: number;
9
+ maxValue?: number;
10
+ enumValues?: (string | number)[];
11
+ items?: ValidationRule;
12
+ properties?: Record<string, ValidationRule>;
13
+ }
14
+ interface ValidationSchema {
15
+ [key: string]: ValidationRule;
16
+ }
17
+ export declare function validate(args: any, schema: ValidationSchema): {
18
+ valid: boolean;
19
+ error?: string;
20
+ };
21
+ export declare const ValidationSchemas: {
22
+ stringArray: (minLength?: number) => ValidationRule;
23
+ entityArray: () => ValidationRule;
24
+ relationArray: () => ValidationRule;
25
+ isoDate: () => ValidationRule;
26
+ nonEmptyString: () => ValidationRule;
27
+ };
28
+ export {};
@@ -0,0 +1,145 @@
1
+ export function validate(args, schema) {
2
+ if (typeof args !== 'object' || args === null) {
3
+ return { valid: false, error: 'Arguments must be an object' };
4
+ }
5
+ for (const [key, rule] of Object.entries(schema)) {
6
+ const value = args[key];
7
+ // Check required
8
+ if (rule.required && (value === undefined || value === null)) {
9
+ return { valid: false, error: `Missing required field: ${key}` };
10
+ }
11
+ if (value === undefined || value === null)
12
+ continue;
13
+ // Type validation
14
+ const result = validateValue(value, rule, key);
15
+ if (!result.valid)
16
+ return result;
17
+ }
18
+ return { valid: true };
19
+ }
20
+ function validateValue(value, rule, path) {
21
+ // Type check
22
+ switch (rule.type) {
23
+ case 'string':
24
+ if (typeof value !== 'string') {
25
+ return { valid: false, error: `${path} must be a string, got ${typeof value}` };
26
+ }
27
+ if (rule.minLength && value.length < rule.minLength) {
28
+ return { valid: false, error: `${path} must be at least ${rule.minLength} characters` };
29
+ }
30
+ if (rule.maxLength && value.length > rule.maxLength) {
31
+ return { valid: false, error: `${path} must be at most ${rule.maxLength} characters` };
32
+ }
33
+ if (rule.pattern && !rule.pattern.test(value)) {
34
+ return { valid: false, error: `${path} format is invalid` };
35
+ }
36
+ if (rule.enumValues && !rule.enumValues.includes(value)) {
37
+ return { valid: false, error: `${path} must be one of: ${rule.enumValues.join(', ')}` };
38
+ }
39
+ break;
40
+ case 'number':
41
+ if (typeof value !== 'number' || isNaN(value)) {
42
+ return { valid: false, error: `${path} must be a number` };
43
+ }
44
+ if (rule.minValue !== undefined && value < rule.minValue) {
45
+ return { valid: false, error: `${path} must be at least ${rule.minValue}` };
46
+ }
47
+ if (rule.maxValue !== undefined && value > rule.maxValue) {
48
+ return { valid: false, error: `${path} must be at most ${rule.maxValue}` };
49
+ }
50
+ if (rule.enumValues && !rule.enumValues.includes(value)) {
51
+ return { valid: false, error: `${path} must be one of: ${rule.enumValues.join(', ')}` };
52
+ }
53
+ break;
54
+ case 'boolean':
55
+ if (typeof value !== 'boolean') {
56
+ return { valid: false, error: `${path} must be a boolean` };
57
+ }
58
+ break;
59
+ case 'date':
60
+ if (typeof value !== 'string') {
61
+ return { valid: false, error: `${path} must be an ISO date string` };
62
+ }
63
+ if (isNaN(Date.parse(value))) {
64
+ return { valid: false, error: `${path} must be a valid ISO date string` };
65
+ }
66
+ break;
67
+ case 'array':
68
+ if (!Array.isArray(value)) {
69
+ return { valid: false, error: `${path} must be an array` };
70
+ }
71
+ if (rule.minLength && value.length < rule.minLength) {
72
+ return { valid: false, error: `${path} must have at least ${rule.minLength} items` };
73
+ }
74
+ if (rule.maxLength && value.length > rule.maxLength) {
75
+ return { valid: false, error: `${path} must have at most ${rule.maxLength} items` };
76
+ }
77
+ if (rule.items) {
78
+ for (let i = 0; i < value.length; i++) {
79
+ const itemResult = validateValue(value[i], rule.items, `${path}[${i}]`);
80
+ if (!itemResult.valid)
81
+ return itemResult;
82
+ }
83
+ }
84
+ break;
85
+ case 'object':
86
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
87
+ return { valid: false, error: `${path} must be an object` };
88
+ }
89
+ if (rule.properties) {
90
+ const nestedResult = validate(value, rule.properties);
91
+ if (!nestedResult.valid) {
92
+ return { valid: false, error: `${path}: ${nestedResult.error}` };
93
+ }
94
+ }
95
+ break;
96
+ case 'enum':
97
+ if (!rule.enumValues?.includes(value)) {
98
+ return { valid: false, error: `${path} must be one of: ${rule.enumValues?.join(', ')}` };
99
+ }
100
+ break;
101
+ }
102
+ return { valid: true };
103
+ }
104
+ // Pre-built schemas for common tool patterns
105
+ export const ValidationSchemas = {
106
+ stringArray: (minLength = 0) => ({
107
+ type: 'array',
108
+ required: true,
109
+ minLength,
110
+ items: { type: 'string' }
111
+ }),
112
+ entityArray: () => ({
113
+ type: 'array',
114
+ required: true,
115
+ items: {
116
+ type: 'object',
117
+ properties: {
118
+ name: { type: 'string', required: true },
119
+ entityType: { type: 'string', required: true },
120
+ observations: { type: 'array', required: true, items: { type: 'string' } }
121
+ }
122
+ }
123
+ }),
124
+ relationArray: () => ({
125
+ type: 'array',
126
+ required: true,
127
+ items: {
128
+ type: 'object',
129
+ properties: {
130
+ from: { type: 'string', required: true },
131
+ to: { type: 'string', required: true },
132
+ relationType: { type: 'string', required: true }
133
+ }
134
+ }
135
+ }),
136
+ isoDate: () => ({
137
+ type: 'date',
138
+ required: true
139
+ }),
140
+ nonEmptyString: () => ({
141
+ type: 'string',
142
+ required: true,
143
+ minLength: 1
144
+ })
145
+ };
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "coaian",
3
+ "version": "0.7.0",
4
+ "description": "Creative Orientation AI Agentic Memories - Narrative Beat Extension with IAIP relational integration",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "bin": {
9
+ "coaia-narrative": "dist/index.js",
10
+ "cnarrative": "dist/cli.js"
11
+ },
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsc --watch",
15
+ "test": "node test-coaia-narrative.js",
16
+ "lint": "eslint index.ts",
17
+ "start": "node dist/index.js",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "keywords": [
21
+ "coaia",
22
+ "narrative",
23
+ "structural-tension-chart",
24
+ "mcp",
25
+ "memory",
26
+ "iaip",
27
+ "four-directions",
28
+ "relational"
29
+ ],
30
+ "author": "avadisabelle",
31
+ "license": "MIT",
32
+ "dependencies": {
33
+ "@modelcontextprotocol/sdk": "^0.6.0",
34
+ "minimist": "^1.2.8",
35
+ "zod": "^3.23.0"
36
+ },
37
+ "peerDependencies": {
38
+ "coaia-memory": "^2.3.1"
39
+ },
40
+ "devDependencies": {
41
+ "@types/minimist": "^1.2.5",
42
+ "@types/node": "^20.0.0",
43
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
44
+ "@typescript-eslint/parser": "^6.0.0",
45
+ "eslint": "^8.0.0",
46
+ "typescript": "^5.0.0"
47
+ },
48
+ "files": [
49
+ "dist/**/*",
50
+ "README.md",
51
+ "LICENSE",
52
+ "DESIGN.md",
53
+ "IMPLEMENTATION_ROADMAP.md"
54
+ ],
55
+ "engines": {
56
+ "node": ">=18.0.0"
57
+ },
58
+ "repository": {
59
+ "type": "git",
60
+ "url": "https://github.com/avadisabelle/coaia-narrative"
61
+ }
62
+ }