konsilio 0.3.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.
Files changed (80) hide show
  1. package/LICENSE.md +24 -0
  2. package/README.md +170 -0
  3. package/build/cli/history.d.ts +2 -0
  4. package/build/cli/history.js +179 -0
  5. package/build/cli/history.js.map +1 -0
  6. package/build/config.d.ts +38 -0
  7. package/build/config.js +118 -0
  8. package/build/config.js.map +1 -0
  9. package/build/container.d.ts +32 -0
  10. package/build/container.js +102 -0
  11. package/build/container.js.map +1 -0
  12. package/build/db/schema.d.ts +1 -0
  13. package/build/db/schema.js +67 -0
  14. package/build/db/schema.js.map +1 -0
  15. package/build/index.d.ts +2 -0
  16. package/build/index.js +140 -0
  17. package/build/index.js.map +1 -0
  18. package/build/konsilio.json +25 -0
  19. package/build/konsilio.schema.json +140 -0
  20. package/build/logger.d.ts +84 -0
  21. package/build/logger.js +121 -0
  22. package/build/logger.js.map +1 -0
  23. package/build/personas/expert.d.ts +33 -0
  24. package/build/personas/expert.js +46 -0
  25. package/build/personas/expert.js.map +1 -0
  26. package/build/personas/index.d.ts +9 -0
  27. package/build/personas/index.js +11 -0
  28. package/build/personas/index.js.map +1 -0
  29. package/build/personas/lead.d.ts +33 -0
  30. package/build/personas/lead.js +51 -0
  31. package/build/personas/lead.js.map +1 -0
  32. package/build/personas/schemas.d.ts +313 -0
  33. package/build/personas/schemas.js +97 -0
  34. package/build/personas/schemas.js.map +1 -0
  35. package/build/prompts/consolidation/critique.md +59 -0
  36. package/build/prompts/consolidation/decision.md +51 -0
  37. package/build/prompts/consolidation/extraction.md +46 -0
  38. package/build/prompts/consolidation/synthesis.md +42 -0
  39. package/build/prompts/expert-rules.md +50 -0
  40. package/build/prompts/personas/dev-tooling.md +27 -0
  41. package/build/prompts/personas/devops.md +26 -0
  42. package/build/prompts/personas/distributed-systems.md +28 -0
  43. package/build/prompts/personas/graph-dba.md +27 -0
  44. package/build/prompts/personas/node-fullstack.md +27 -0
  45. package/build/prompts/personas/performance.md +26 -0
  46. package/build/prompts/personas/security.md +26 -0
  47. package/build/prompts/personas/test-architect.md +29 -0
  48. package/build/prompts/personas/test-quoted.md +14 -0
  49. package/build/prompts/personas/typescript.md +26 -0
  50. package/build/prompts/personas/ux-dx.md +29 -0
  51. package/build/prompts/workflow-rules.md +3 -0
  52. package/build/server.d.ts +24 -0
  53. package/build/server.js +181 -0
  54. package/build/server.js.map +1 -0
  55. package/build/services/cache.service.d.ts +49 -0
  56. package/build/services/cache.service.js +85 -0
  57. package/build/services/cache.service.js.map +1 -0
  58. package/build/services/council.service.d.ts +111 -0
  59. package/build/services/council.service.js +361 -0
  60. package/build/services/council.service.js.map +1 -0
  61. package/build/services/database.service.d.ts +70 -0
  62. package/build/services/database.service.js +221 -0
  63. package/build/services/database.service.js.map +1 -0
  64. package/build/services/formatter.service.d.ts +52 -0
  65. package/build/services/formatter.service.js +133 -0
  66. package/build/services/formatter.service.js.map +1 -0
  67. package/build/services/index.d.ts +18 -0
  68. package/build/services/index.js +13 -0
  69. package/build/services/index.js.map +1 -0
  70. package/build/services/openrouter.service.d.ts +58 -0
  71. package/build/services/openrouter.service.js +128 -0
  72. package/build/services/openrouter.service.js.map +1 -0
  73. package/build/services/persona.service.d.ts +43 -0
  74. package/build/services/persona.service.js +93 -0
  75. package/build/services/persona.service.js.map +1 -0
  76. package/build/services/prompt.service.d.ts +59 -0
  77. package/build/services/prompt.service.js +209 -0
  78. package/build/services/prompt.service.js.map +1 -0
  79. package/konsilio.schema.json +140 -0
  80. package/package.json +68 -0
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Persona Service
3
+ *
4
+ * Provides persona creation and management.
5
+ * Designed for dependency injection to enable testing.
6
+ */
7
+ import type { Logger } from '../logger.js';
8
+ import type { CacheService } from './cache.service.js';
9
+ import type { PromptService } from './prompt.service.js';
10
+ import type { Persona } from '../personas/schemas.js';
11
+ /**
12
+ * PersonaService - Creates and manages personas
13
+ */
14
+ export declare class PersonaService {
15
+ private readonly deps;
16
+ private readonly expertRules;
17
+ private readonly workflowRules;
18
+ private readonly cacheTtlMs;
19
+ constructor(deps: {
20
+ promptService: PromptService;
21
+ cacheService?: CacheService;
22
+ logger: Logger;
23
+ });
24
+ /**
25
+ * Create multiple expert personas
26
+ * Used by: CouncilService for expert analysis phase
27
+ */
28
+ createExperts(personaIds: string[], model: string): Persona[];
29
+ /**
30
+ * Create lead persona for consolidation phase
31
+ * Used by: CouncilService for extraction, critique, decision, synthesis phases
32
+ */
33
+ createLead(phase: 'extraction' | 'critique' | 'decision' | 'synthesis'): Persona;
34
+ /**
35
+ * Get available persona IDs from prompts directory
36
+ * Used by: CLI for listing available personas
37
+ */
38
+ getAvailablePersonaIds(): string[];
39
+ /**
40
+ * Create a single expert persona
41
+ */
42
+ createExpert(personaId: string, model: string): Persona;
43
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Persona Service
3
+ *
4
+ * Provides persona creation and management.
5
+ * Designed for dependency injection to enable testing.
6
+ */
7
+ import { Expert } from '../personas/expert.js';
8
+ import { Lead } from '../personas/lead.js';
9
+ /**
10
+ * PersonaService - Creates and manages personas
11
+ */
12
+ export class PersonaService {
13
+ deps;
14
+ expertRules;
15
+ workflowRules;
16
+ cacheTtlMs = 300_000; // 5 minutes
17
+ constructor(deps) {
18
+ this.deps = deps;
19
+ // Load rules once at construction (they rarely change)
20
+ this.expertRules = deps.promptService.loadCoreRules();
21
+ this.workflowRules = deps.promptService.loadWorkflowRules();
22
+ }
23
+ /**
24
+ * Create multiple expert personas
25
+ * Used by: CouncilService for expert analysis phase
26
+ */
27
+ createExperts(personaIds, model) {
28
+ return personaIds.map(id => this.createExpert(id, model));
29
+ }
30
+ /**
31
+ * Create lead persona for consolidation phase
32
+ * Used by: CouncilService for extraction, critique, decision, synthesis phases
33
+ */
34
+ createLead(phase) {
35
+ const cacheKey = `lead:${phase}`;
36
+ // Check cache
37
+ const cached = this.deps.cacheService?.get(cacheKey);
38
+ if (cached) {
39
+ this.deps.logger.debug('Lead persona loaded from cache', { phase });
40
+ return cached;
41
+ }
42
+ const lead = new Lead({
43
+ phase,
44
+ workflowRules: this.workflowRules,
45
+ promptService: this.deps.promptService,
46
+ });
47
+ // Cache the lead
48
+ this.deps.cacheService?.set(cacheKey, lead, this.cacheTtlMs);
49
+ return lead;
50
+ }
51
+ /**
52
+ * Get available persona IDs from prompts directory
53
+ * Used by: CLI for listing available personas
54
+ */
55
+ getAvailablePersonaIds() {
56
+ // These are the persona IDs that have markdown files
57
+ return [
58
+ 'security',
59
+ 'performance',
60
+ 'ux-dx',
61
+ 'devops',
62
+ 'typescript',
63
+ 'graph-dba',
64
+ 'node-fullstack',
65
+ 'dev-tooling',
66
+ 'distributed-systems',
67
+ 'test-architect',
68
+ ];
69
+ }
70
+ /**
71
+ * Create a single expert persona
72
+ */
73
+ createExpert(personaId, model) {
74
+ const cacheKey = `expert:${personaId}:${model}`;
75
+ // Check cache
76
+ const cached = this.deps.cacheService?.get(cacheKey);
77
+ if (cached) {
78
+ this.deps.logger.debug('Expert persona loaded from cache', { personaId });
79
+ return cached;
80
+ }
81
+ const expert = new Expert({
82
+ personaId,
83
+ model,
84
+ expertRules: this.expertRules,
85
+ workflowRules: this.workflowRules,
86
+ promptService: this.deps.promptService,
87
+ });
88
+ // Cache the expert
89
+ this.deps.cacheService?.set(cacheKey, expert, this.cacheTtlMs);
90
+ return expert;
91
+ }
92
+ }
93
+ //# sourceMappingURL=persona.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persona.service.js","sourceRoot":"","sources":["../../src/services/persona.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C;;GAEG;AACH,MAAM,OAAO,cAAc;IAMN;IALF,WAAW,CAAS;IACpB,aAAa,CAAS;IACtB,UAAU,GAAG,OAAO,CAAC,CAAC,YAAY;IAEnD,YACmB,IAIhB;QAJgB,SAAI,GAAJ,IAAI,CAIpB;QAED,uDAAuD;QACvD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;QACtD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,CAAC;IAC9D,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,UAAoB,EAAE,KAAa;QAC/C,OAAO,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,KAA2D;QACpE,MAAM,QAAQ,GAAG,QAAQ,KAAK,EAAE,CAAC;QAEjC,cAAc;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAU,QAAQ,CAAC,CAAC;QAC9D,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACpE,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC;YACpB,KAAK;YACL,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa;SACvC,CAAC,CAAC;QAEH,iBAAiB;QACjB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAE7D,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,sBAAsB;QACpB,qDAAqD;QACrD,OAAO;YACL,UAAU;YACV,aAAa;YACb,OAAO;YACP,QAAQ;YACR,YAAY;YACZ,WAAW;YACX,gBAAgB;YAChB,aAAa;YACb,qBAAqB;YACrB,gBAAgB;SACjB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,SAAiB,EAAE,KAAa;QAC3C,MAAM,QAAQ,GAAG,UAAU,SAAS,IAAI,KAAK,EAAE,CAAC;QAEhD,cAAc;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAU,QAAQ,CAAC,CAAC;QAC9D,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;YAC1E,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;YACxB,SAAS;YACT,KAAK;YACL,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa;SACvC,CAAC,CAAC;QAEH,mBAAmB;QACnB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAE/D,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Prompt Service
3
+ *
4
+ * Loads prompt content from markdown files.
5
+ * Designed for dependency injection to enable testing.
6
+ */
7
+ import type { Logger } from '../logger.js';
8
+ export interface PromptServiceConfig {
9
+ /** Root directory for prompt files */
10
+ promptsDir?: string;
11
+ }
12
+ export interface PersonaPromptData {
13
+ id: string;
14
+ name: string;
15
+ emoji: string;
16
+ focusAreas: string[];
17
+ domains?: string[];
18
+ antiPatterns: string[];
19
+ }
20
+ /**
21
+ * PromptService - Loads prompt content from markdown files
22
+ */
23
+ export declare class PromptService {
24
+ private readonly promptsDir;
25
+ private readonly logger;
26
+ constructor(config: PromptServiceConfig | undefined, logger: Logger);
27
+ /**
28
+ * Load persona prompt data from markdown file
29
+ */
30
+ loadPersonaPromptData(personaId: string): PersonaPromptData;
31
+ /**
32
+ * Load consolidation phase prompt from markdown file
33
+ */
34
+ loadConsolidationPhase(phase: 'extraction' | 'critique' | 'decision' | 'synthesis'): string;
35
+ /**
36
+ * Load expert rules from markdown file
37
+ */
38
+ loadCoreRules(): string;
39
+ /**
40
+ * Load workflow rules from markdown file
41
+ */
42
+ loadWorkflowRules(): string;
43
+ /**
44
+ * Parse persona prompt data from markdown content
45
+ */
46
+ private parsePersonaPromptData;
47
+ /**
48
+ * Extract YAML frontmatter from markdown content
49
+ */
50
+ private extractYamlFrontmatter;
51
+ /**
52
+ * Extract anti-patterns from markdown content
53
+ */
54
+ private extractAntiPatterns;
55
+ /**
56
+ * Default prompt data when file not found
57
+ */
58
+ private getDefaultPersonaPromptData;
59
+ }
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Prompt Service
3
+ *
4
+ * Loads prompt content from markdown files.
5
+ * Designed for dependency injection to enable testing.
6
+ */
7
+ import { readFileSync, existsSync } from 'node:fs';
8
+ import { join, dirname } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+ /**
12
+ * PromptService - Loads prompt content from markdown files
13
+ */
14
+ export class PromptService {
15
+ promptsDir;
16
+ logger;
17
+ constructor(config, logger) {
18
+ // Resolve prompts relative to project root (data/prompts/ at runtime)
19
+ // During development, falls back to src/prompts/ if data/prompts/ doesn't exist
20
+ const projectRoot = join(__dirname, '..', '..');
21
+ const dataPrompts = join(projectRoot, 'data', 'prompts');
22
+ const srcPrompts = join(__dirname, '..', 'prompts');
23
+ // Prefer data/prompts/ (runtime), fall back to src/prompts/ (development)
24
+ this.promptsDir = config?.promptsDir ?? (existsSync(dataPrompts) ? dataPrompts : srcPrompts);
25
+ this.logger = logger;
26
+ }
27
+ /**
28
+ * Load persona prompt data from markdown file
29
+ */
30
+ loadPersonaPromptData(personaId) {
31
+ const filePath = join(this.promptsDir, 'personas', `${personaId}.md`);
32
+ if (!existsSync(filePath)) {
33
+ this.logger.warn(`Persona prompt file not found: ${filePath}, using defaults`);
34
+ return this.getDefaultPersonaPromptData();
35
+ }
36
+ try {
37
+ const content = readFileSync(filePath, 'utf-8');
38
+ return this.parsePersonaPromptData(content);
39
+ }
40
+ catch (err) {
41
+ this.logger.error(`Failed to load persona prompt: ${personaId}`, {
42
+ error: err instanceof Error ? err.message : String(err),
43
+ });
44
+ return this.getDefaultPersonaPromptData();
45
+ }
46
+ }
47
+ /**
48
+ * Load consolidation phase prompt from markdown file
49
+ */
50
+ loadConsolidationPhase(phase) {
51
+ const filePath = join(this.promptsDir, 'consolidation', `${phase}.md`);
52
+ if (!existsSync(filePath)) {
53
+ this.logger.warn(`Consolidation phase file not found: ${filePath}`);
54
+ return '';
55
+ }
56
+ try {
57
+ return readFileSync(filePath, 'utf-8');
58
+ }
59
+ catch (err) {
60
+ this.logger.error(`Failed to load consolidation phase: ${phase}`, {
61
+ error: err instanceof Error ? err.message : String(err),
62
+ });
63
+ return '';
64
+ }
65
+ }
66
+ /**
67
+ * Load expert rules from markdown file
68
+ */
69
+ loadCoreRules() {
70
+ const filePath = join(this.promptsDir, 'expert-rules.md');
71
+ if (!existsSync(filePath)) {
72
+ this.logger.warn(`Expert rules file not found: ${filePath}`);
73
+ return '';
74
+ }
75
+ try {
76
+ return readFileSync(filePath, 'utf-8');
77
+ }
78
+ catch (err) {
79
+ this.logger.error('Failed to load expert rules', {
80
+ error: err instanceof Error ? err.message : String(err),
81
+ });
82
+ return '';
83
+ }
84
+ }
85
+ /**
86
+ * Load workflow rules from markdown file
87
+ */
88
+ loadWorkflowRules() {
89
+ const filePath = join(this.promptsDir, 'workflow-rules.md');
90
+ if (!existsSync(filePath)) {
91
+ this.logger.warn(`Workflow rules file not found: ${filePath}`);
92
+ return '';
93
+ }
94
+ try {
95
+ return readFileSync(filePath, 'utf-8');
96
+ }
97
+ catch (err) {
98
+ this.logger.error('Failed to load workflow rules', {
99
+ error: err instanceof Error ? err.message : String(err),
100
+ });
101
+ return '';
102
+ }
103
+ }
104
+ /**
105
+ * Parse persona prompt data from markdown content
106
+ */
107
+ parsePersonaPromptData(content) {
108
+ const metadata = this.extractYamlFrontmatter(content);
109
+ const antiPatterns = this.extractAntiPatterns(content);
110
+ return {
111
+ id: metadata.id,
112
+ name: metadata.name,
113
+ emoji: metadata.emoji,
114
+ focusAreas: metadata.focusAreas,
115
+ domains: metadata.domains,
116
+ antiPatterns,
117
+ };
118
+ }
119
+ /**
120
+ * Extract YAML frontmatter from markdown content
121
+ */
122
+ extractYamlFrontmatter(content) {
123
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
124
+ if (!match) {
125
+ this.logger.warn('No YAML frontmatter found in persona markdown file');
126
+ return { id: '', name: '', emoji: '', focusAreas: [] };
127
+ }
128
+ const yaml = match[1];
129
+ const result = {
130
+ id: '',
131
+ name: '',
132
+ emoji: '',
133
+ focusAreas: [],
134
+ domains: undefined,
135
+ };
136
+ // Simple YAML parsing for our specific format
137
+ const lines = yaml.split(/\r?\n/);
138
+ let currentKey = '';
139
+ let currentArray = [];
140
+ for (const line of lines) {
141
+ const trimmed = line.trim();
142
+ // Skip empty lines
143
+ if (!trimmed)
144
+ continue;
145
+ // Check if it's an array item
146
+ if (trimmed.startsWith('- ')) {
147
+ currentArray.push(trimmed.slice(2).trim());
148
+ continue;
149
+ }
150
+ // If we were building an array, save it and reset
151
+ if (currentKey && currentArray.length > 0) {
152
+ result[currentKey] = [...currentArray];
153
+ currentKey = '';
154
+ currentArray = [];
155
+ }
156
+ // Parse key: value
157
+ const colonIndex = trimmed.indexOf(':');
158
+ if (colonIndex > 0) {
159
+ const key = trimmed.slice(0, colonIndex).trim();
160
+ let value = trimmed.slice(colonIndex + 1).trim();
161
+ // Remove quotes if present
162
+ if ((value.startsWith('"') && value.endsWith('"')) ||
163
+ (value.startsWith("'") && value.endsWith("'"))) {
164
+ value = value.slice(1, -1);
165
+ }
166
+ if (value) {
167
+ result[key] = value;
168
+ }
169
+ else {
170
+ // Empty value means this is an array key
171
+ currentKey = key;
172
+ currentArray = [];
173
+ }
174
+ }
175
+ }
176
+ // Save any remaining array
177
+ if (currentKey && currentArray.length > 0) {
178
+ result[currentKey] = [...currentArray];
179
+ }
180
+ return result;
181
+ }
182
+ /**
183
+ * Extract anti-patterns from markdown content
184
+ */
185
+ extractAntiPatterns(content) {
186
+ // Find the Anti-Patterns section and extract list items
187
+ const match = content.match(/## Anti-Patterns\r?\n\r?\n([\s\S]*?)(?=\r?\n## |$)/);
188
+ if (!match)
189
+ return [];
190
+ return match[1]
191
+ .split(/\r?\n/)
192
+ .filter(line => line.startsWith('- '))
193
+ .map(line => line.slice(2).trim());
194
+ }
195
+ /**
196
+ * Default prompt data when file not found
197
+ */
198
+ getDefaultPersonaPromptData() {
199
+ return {
200
+ id: 'unknown',
201
+ name: 'Unknown Persona',
202
+ emoji: '?',
203
+ focusAreas: [],
204
+ domains: [],
205
+ antiPatterns: [],
206
+ };
207
+ }
208
+ }
209
+ //# sourceMappingURL=prompt.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.service.js","sourceRoot":"","sources":["../../src/services/prompt.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Konsilio Configuration",
4
+ "description": "Configuration file for the Konsilio Council of Experts MCP server",
5
+ "type": "object",
6
+ "properties": {
7
+ "$schema": {
8
+ "type": "string",
9
+ "description": "Path to this JSON schema file for IDE validation"
10
+ },
11
+ "personas": {
12
+ "type": "object",
13
+ "description": "Persona configuration for expert analysis",
14
+ "properties": {
15
+ "enabled": {
16
+ "type": "array",
17
+ "items": {
18
+ "type": "string",
19
+ "description": "Persona ID (e.g., security, performance, ux-dx, devops, or custom personas)"
20
+ },
21
+ "minItems": 2,
22
+ "description": "Expert personas to include in council consultations. Must have at least 2. Built-in personas: security, performance, ux-dx, devops, typescript, graph-dba, node-fullstack, dev-tooling, distributed-systems, test-architect"
23
+ }
24
+ },
25
+ "required": ["enabled"],
26
+ "additionalProperties": false
27
+ },
28
+ "constitution": {
29
+ "type": "string",
30
+ "description": "Path to optional constitution file with custom workflow rules"
31
+ },
32
+ "models": {
33
+ "type": "object",
34
+ "description": "Default model configuration for all personas",
35
+ "properties": {
36
+ "experts": {
37
+ "type": "string",
38
+ "description": "Default model for expert personas. Override per-persona with personaModels."
39
+ },
40
+ "lead": {
41
+ "type": "string",
42
+ "description": "Model for consolidation phases (extraction, critique, decision, synthesis)"
43
+ },
44
+ "formatter": {
45
+ "type": "string",
46
+ "description": "Model used to format prose into structured JSON"
47
+ }
48
+ },
49
+ "additionalProperties": false
50
+ },
51
+ "personaModels": {
52
+ "type": "object",
53
+ "description": "Per-persona model defaults. Maps personaId to model ID. Overrides models.experts for specific personas.",
54
+ "additionalProperties": {
55
+ "type": "string",
56
+ "description": "OpenRouter model ID for this persona"
57
+ },
58
+ "examples": [
59
+ {
60
+ "security": "openai/gpt-4o",
61
+ "performance": "anthropic/claude-sonnet-4"
62
+ }
63
+ ]
64
+ },
65
+ "timeouts": {
66
+ "type": "object",
67
+ "description": "Timeout configuration for API calls",
68
+ "properties": {
69
+ "expertMs": {
70
+ "type": "integer",
71
+ "minimum": 10000,
72
+ "description": "Timeout for expert analysis in milliseconds"
73
+ },
74
+ "leadMs": {
75
+ "type": "integer",
76
+ "minimum": 30000,
77
+ "description": "Timeout for consolidation phases in milliseconds"
78
+ },
79
+ "formatterMs": {
80
+ "type": "integer",
81
+ "minimum": 10000,
82
+ "description": "Timeout for formatting prose in milliseconds"
83
+ }
84
+ },
85
+ "additionalProperties": false
86
+ },
87
+ "maxTokens": {
88
+ "type": "object",
89
+ "description": "Token limits for API calls",
90
+ "properties": {
91
+ "experts": {
92
+ "type": "integer",
93
+ "minimum": 100,
94
+ "description": "Max tokens per expert analysis"
95
+ },
96
+ "lead": {
97
+ "type": "integer",
98
+ "minimum": 100,
99
+ "description": "Max tokens for consolidation phases"
100
+ }
101
+ },
102
+ "additionalProperties": false
103
+ },
104
+ "maxDraftPlanLength": {
105
+ "type": "integer",
106
+ "minimum": 1000,
107
+ "description": "Maximum length of draft plan input in characters"
108
+ },
109
+ "maxHistorySessions": {
110
+ "type": "integer",
111
+ "minimum": 1,
112
+ "maximum": 100,
113
+ "description": "Maximum number of session history entries to retain"
114
+ },
115
+ "databasePath": {
116
+ "type": "string",
117
+ "description": "Path to SQLite database file for session storage"
118
+ },
119
+ "cacheTtlSeconds": {
120
+ "type": "integer",
121
+ "minimum": 60,
122
+ "description": "Cache time-to-live in seconds for persona data"
123
+ },
124
+ "formatter": {
125
+ "type": "object",
126
+ "description": "Formatter service configuration",
127
+ "properties": {
128
+ "maxRetries": {
129
+ "type": "integer",
130
+ "minimum": 0,
131
+ "maximum": 10,
132
+ "description": "Maximum retries for formatting failures"
133
+ }
134
+ },
135
+ "additionalProperties": false
136
+ }
137
+ },
138
+ "required": ["personas"],
139
+ "additionalProperties": false
140
+ }
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "konsilio",
3
+ "version": "0.3.0",
4
+ "description": "Konsilio MCP server runs draft plans through a multi-persona architectural review.",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "code-review",
9
+ "architecture",
10
+ "ai",
11
+ "multi-agent",
12
+ "expert-system",
13
+ "planning",
14
+ "consulting",
15
+ "blueprint"
16
+ ],
17
+ "homepage": "https://github.com/edzillion/konsilio#readme",
18
+ "bugs": {
19
+ "url": "https://github.com/edzillion/konsilio/issues"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/edzillion/konsilio.git"
24
+ },
25
+ "license": "Unlicense",
26
+ "author": "edzillion",
27
+ "type": "module",
28
+ "exports": {
29
+ ".": "./build/index.js",
30
+ "./schema": "./konsilio.schema.json"
31
+ },
32
+ "main": "build/index.js",
33
+ "types": "./build/index.d.ts",
34
+ "bin": {
35
+ "konsilio": "build/index.js"
36
+ },
37
+ "files": [
38
+ "build/",
39
+ "konsilio.schema.json"
40
+ ],
41
+ "scripts": {
42
+ "build": "tsc -p tsconfig.build.json && node scripts/copy-assets.mjs",
43
+ "dev": "tsc --watch",
44
+ "start": "node build/index.js",
45
+ "start:server": "node build/server.js",
46
+ "inspect": "npx @modelcontextprotocol/inspector node /g/dev/konsilio/build/index.js",
47
+ "typecheck": "tsc --noEmit",
48
+ "history": "node build/cli/history.js",
49
+ "test": "vitest run --reporter=verbose",
50
+ "test-agent": "vitest run --reporter=json | jq \".testResults[] | {name, status, errors}\"",
51
+ "test:watch": "vitest",
52
+ "test:coverage": "vitest run --coverage"
53
+ },
54
+ "dependencies": {
55
+ "@modelcontextprotocol/sdk": "^1.28.0",
56
+ "pino": "^10.3.1",
57
+ "sql.js": "^1.14.1",
58
+ "zod": "^4.3.6"
59
+ },
60
+ "devDependencies": {
61
+ "@modelcontextprotocol/inspector": "^0.21.1",
62
+ "@types/node": "^25.5.0",
63
+ "@types/sql.js": "^1.4.11",
64
+ "@vitest/coverage-v8": "^4.1.2",
65
+ "typescript": "^6.0.2",
66
+ "vitest": "^4.1.2"
67
+ }
68
+ }