@hiveforge/hivemind-mcp 2.4.0 → 2.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 +70 -8
- package/dist/cli.js +938 -77
- package/dist/cli.js.map +1 -1
- package/dist/config/schema.d.ts +125 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +79 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -2
- package/dist/index.js.map +1 -1
- package/dist/templates/builtin/people-management.d.ts.map +1 -1
- package/dist/templates/builtin/people-management.js +10 -0
- package/dist/templates/builtin/people-management.js.map +1 -1
- package/dist/templates/builtin/research.d.ts.map +1 -1
- package/dist/templates/builtin/research.js +10 -0
- package/dist/templates/builtin/research.js.map +1 -1
- package/dist/templates/builtin/worldbuilding.d.ts.map +1 -1
- package/dist/templates/builtin/worldbuilding.js +10 -0
- package/dist/templates/builtin/worldbuilding.js.map +1 -1
- package/dist/templates/community/architecture.d.ts +19 -0
- package/dist/templates/community/architecture.d.ts.map +1 -0
- package/dist/templates/community/architecture.js +296 -0
- package/dist/templates/community/architecture.js.map +1 -0
- package/dist/templates/community/index.d.ts +37 -0
- package/dist/templates/community/index.d.ts.map +1 -0
- package/dist/templates/community/index.js +45 -0
- package/dist/templates/community/index.js.map +1 -0
- package/dist/templates/community/ux-research.d.ts +21 -0
- package/dist/templates/community/ux-research.d.ts.map +1 -0
- package/dist/templates/community/ux-research.js +347 -0
- package/dist/templates/community/ux-research.js.map +1 -0
- package/dist/templates/loader.d.ts +62 -7
- package/dist/templates/loader.d.ts.map +1 -1
- package/dist/templates/loader.js +132 -11
- package/dist/templates/loader.js.map +1 -1
- package/dist/templates/types.d.ts +29 -0
- package/dist/templates/types.d.ts.map +1 -1
- package/dist/templates/validator.d.ts +56 -0
- package/dist/templates/validator.d.ts.map +1 -1
- package/dist/templates/validator.js +32 -0
- package/dist/templates/validator.js.map +1 -1
- package/dist/templates/version.d.ts +63 -0
- package/dist/templates/version.d.ts.map +1 -0
- package/dist/templates/version.js +119 -0
- package/dist/templates/version.js.map +1 -0
- package/dist/types/index.d.ts +12 -12
- package/package.json +1 -1
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UX Research Template
|
|
3
|
+
*
|
|
4
|
+
* For synthesizing user research: interviews, insights, hypotheses, and personas.
|
|
5
|
+
* Helps AI understand the evidence behind product decisions and user needs.
|
|
6
|
+
*
|
|
7
|
+
* Entity types:
|
|
8
|
+
* - interview: Individual research sessions with participants
|
|
9
|
+
* - insight: Key learnings derived from research
|
|
10
|
+
* - hypothesis: Testable assumptions about user behavior
|
|
11
|
+
* - persona: Archetypal user representations
|
|
12
|
+
* - experiment: Tests to validate or invalidate hypotheses
|
|
13
|
+
*
|
|
14
|
+
* Key relationships:
|
|
15
|
+
* - supports/contradicts: Evidence relationships
|
|
16
|
+
* - derived_from: Traceability to source research
|
|
17
|
+
* - validates/invalidates: Experiment outcomes
|
|
18
|
+
*/
|
|
19
|
+
export const uxResearchTemplate = {
|
|
20
|
+
id: 'ux-research',
|
|
21
|
+
name: 'UX Research',
|
|
22
|
+
version: '1.0.0',
|
|
23
|
+
description: 'Synthesize user research: interviews, insights, hypotheses, and personas. Gives AI grounded context about user needs and product decisions.',
|
|
24
|
+
// Discovery metadata
|
|
25
|
+
category: 'research',
|
|
26
|
+
tags: ['ux', 'user-research', 'interviews', 'personas', 'insights', 'product-management'],
|
|
27
|
+
author: {
|
|
28
|
+
name: 'HiveForge',
|
|
29
|
+
url: 'https://github.com/hiveforge-sh',
|
|
30
|
+
},
|
|
31
|
+
repository: 'https://github.com/hiveforge-sh/hivemind',
|
|
32
|
+
sampleVault: 'samples/ux-research',
|
|
33
|
+
license: 'MIT',
|
|
34
|
+
entityTypes: [
|
|
35
|
+
{
|
|
36
|
+
name: 'interview',
|
|
37
|
+
displayName: 'Interview',
|
|
38
|
+
pluralName: 'Interviews',
|
|
39
|
+
description: 'A research session with a participant',
|
|
40
|
+
fields: [
|
|
41
|
+
{
|
|
42
|
+
name: 'participant',
|
|
43
|
+
type: 'string',
|
|
44
|
+
required: true,
|
|
45
|
+
description: 'Anonymized participant identifier (e.g., P01, "Enterprise User 3")',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'date',
|
|
49
|
+
type: 'date',
|
|
50
|
+
required: true,
|
|
51
|
+
description: 'Date the interview was conducted',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'duration',
|
|
55
|
+
type: 'number',
|
|
56
|
+
description: 'Duration in minutes',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'method',
|
|
60
|
+
type: 'enum',
|
|
61
|
+
enumValues: ['in-person', 'video', 'phone', 'survey', 'contextual-inquiry', 'usability-test'],
|
|
62
|
+
description: 'Research method used',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'segment',
|
|
66
|
+
type: 'string',
|
|
67
|
+
description: 'User segment (e.g., "Power Users", "New Customers")',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'researcher',
|
|
71
|
+
type: 'string',
|
|
72
|
+
description: 'Who conducted the interview',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'recordingUrl',
|
|
76
|
+
type: 'string',
|
|
77
|
+
description: 'Link to recording (if available)',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: 'keyQuotes',
|
|
81
|
+
type: 'array',
|
|
82
|
+
arrayItemType: 'string',
|
|
83
|
+
description: 'Notable verbatim quotes from participant',
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'insight',
|
|
89
|
+
displayName: 'Insight',
|
|
90
|
+
pluralName: 'Insights',
|
|
91
|
+
description: 'A key learning derived from research',
|
|
92
|
+
fields: [
|
|
93
|
+
{
|
|
94
|
+
name: 'confidence',
|
|
95
|
+
type: 'enum',
|
|
96
|
+
enumValues: ['low', 'medium', 'high'],
|
|
97
|
+
description: 'Confidence level based on evidence strength',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'theme',
|
|
101
|
+
type: 'string',
|
|
102
|
+
description: 'Research theme or category',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'impact',
|
|
106
|
+
type: 'enum',
|
|
107
|
+
enumValues: ['low', 'medium', 'high', 'critical'],
|
|
108
|
+
description: 'Potential business/product impact',
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'evidenceCount',
|
|
112
|
+
type: 'number',
|
|
113
|
+
description: 'Number of supporting data points',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'quotes',
|
|
117
|
+
type: 'array',
|
|
118
|
+
arrayItemType: 'string',
|
|
119
|
+
description: 'Supporting quotes from research',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: 'actionable',
|
|
123
|
+
type: 'boolean',
|
|
124
|
+
description: 'Whether this insight has clear next steps',
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'hypothesis',
|
|
130
|
+
displayName: 'Hypothesis',
|
|
131
|
+
pluralName: 'Hypotheses',
|
|
132
|
+
description: 'A testable assumption about user behavior or needs',
|
|
133
|
+
fields: [
|
|
134
|
+
{
|
|
135
|
+
name: 'hypothesisStatus',
|
|
136
|
+
type: 'enum',
|
|
137
|
+
enumValues: ['untested', 'testing', 'validated', 'invalidated', 'partially-validated'],
|
|
138
|
+
required: true,
|
|
139
|
+
description: 'Current validation status',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: 'statement',
|
|
143
|
+
type: 'string',
|
|
144
|
+
description: 'Formal hypothesis statement (We believe that... We will know we are right when...)',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: 'metric',
|
|
148
|
+
type: 'string',
|
|
149
|
+
description: 'Key metric to measure',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: 'target',
|
|
153
|
+
type: 'string',
|
|
154
|
+
description: 'Success threshold for the metric',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'priority',
|
|
158
|
+
type: 'enum',
|
|
159
|
+
enumValues: ['low', 'medium', 'high', 'critical'],
|
|
160
|
+
description: 'Priority for testing',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'riskIfWrong',
|
|
164
|
+
type: 'string',
|
|
165
|
+
description: 'What happens if this hypothesis is wrong',
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
name: 'persona',
|
|
171
|
+
displayName: 'Persona',
|
|
172
|
+
pluralName: 'Personas',
|
|
173
|
+
description: 'An archetypal user representation based on research',
|
|
174
|
+
fields: [
|
|
175
|
+
{
|
|
176
|
+
name: 'segment',
|
|
177
|
+
type: 'string',
|
|
178
|
+
required: true,
|
|
179
|
+
description: 'Market or user segment this persona represents',
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: 'role',
|
|
183
|
+
type: 'string',
|
|
184
|
+
description: 'Job title or role',
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: 'goals',
|
|
188
|
+
type: 'array',
|
|
189
|
+
arrayItemType: 'string',
|
|
190
|
+
description: 'Primary goals and motivations',
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: 'frustrations',
|
|
194
|
+
type: 'array',
|
|
195
|
+
arrayItemType: 'string',
|
|
196
|
+
description: 'Pain points and frustrations',
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'behaviors',
|
|
200
|
+
type: 'array',
|
|
201
|
+
arrayItemType: 'string',
|
|
202
|
+
description: 'Typical behaviors and patterns',
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: 'tools',
|
|
206
|
+
type: 'array',
|
|
207
|
+
arrayItemType: 'string',
|
|
208
|
+
description: 'Tools and technologies they use',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: 'quote',
|
|
212
|
+
type: 'string',
|
|
213
|
+
description: 'Representative quote that captures their mindset',
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
name: 'interviewCount',
|
|
217
|
+
type: 'number',
|
|
218
|
+
description: 'Number of interviews this persona is based on',
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: 'experiment',
|
|
224
|
+
displayName: 'Experiment',
|
|
225
|
+
pluralName: 'Experiments',
|
|
226
|
+
description: 'A test designed to validate or invalidate a hypothesis',
|
|
227
|
+
fields: [
|
|
228
|
+
{
|
|
229
|
+
name: 'experimentStatus',
|
|
230
|
+
type: 'enum',
|
|
231
|
+
enumValues: ['planned', 'running', 'completed', 'cancelled'],
|
|
232
|
+
required: true,
|
|
233
|
+
description: 'Current status of the experiment',
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: 'experimentType',
|
|
237
|
+
type: 'enum',
|
|
238
|
+
enumValues: ['a-b-test', 'usability-test', 'prototype-test', 'survey', 'analytics', 'fake-door', 'wizard-of-oz'],
|
|
239
|
+
description: 'Type of experiment',
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: 'startDate',
|
|
243
|
+
type: 'date',
|
|
244
|
+
description: 'When the experiment started',
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: 'endDate',
|
|
248
|
+
type: 'date',
|
|
249
|
+
description: 'When the experiment ended',
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: 'sampleSize',
|
|
253
|
+
type: 'number',
|
|
254
|
+
description: 'Number of participants or data points',
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: 'result',
|
|
258
|
+
type: 'enum',
|
|
259
|
+
enumValues: ['positive', 'negative', 'inconclusive', 'pending'],
|
|
260
|
+
description: 'Outcome of the experiment',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: 'learnings',
|
|
264
|
+
type: 'array',
|
|
265
|
+
arrayItemType: 'string',
|
|
266
|
+
description: 'Key learnings from the experiment',
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
relationshipTypes: [
|
|
272
|
+
{
|
|
273
|
+
id: 'supports',
|
|
274
|
+
displayName: 'Supports',
|
|
275
|
+
description: 'Evidence that supports a hypothesis or insight',
|
|
276
|
+
sourceTypes: ['interview', 'insight', 'experiment'],
|
|
277
|
+
targetTypes: ['hypothesis', 'insight'],
|
|
278
|
+
bidirectional: false,
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
id: 'contradicts',
|
|
282
|
+
displayName: 'Contradicts',
|
|
283
|
+
description: 'Evidence that contradicts a hypothesis or insight',
|
|
284
|
+
sourceTypes: ['interview', 'insight', 'experiment'],
|
|
285
|
+
targetTypes: ['hypothesis', 'insight'],
|
|
286
|
+
bidirectional: false,
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
id: 'derived_from',
|
|
290
|
+
displayName: 'Derived From',
|
|
291
|
+
description: 'Insight or persona derived from interviews',
|
|
292
|
+
sourceTypes: ['insight', 'persona'],
|
|
293
|
+
targetTypes: ['interview'],
|
|
294
|
+
bidirectional: false,
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
id: 'validates',
|
|
298
|
+
displayName: 'Validates',
|
|
299
|
+
description: 'Experiment validates a hypothesis',
|
|
300
|
+
sourceTypes: ['experiment'],
|
|
301
|
+
targetTypes: ['hypothesis'],
|
|
302
|
+
bidirectional: false,
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: 'invalidates',
|
|
306
|
+
displayName: 'Invalidates',
|
|
307
|
+
description: 'Experiment invalidates a hypothesis',
|
|
308
|
+
sourceTypes: ['experiment'],
|
|
309
|
+
targetTypes: ['hypothesis'],
|
|
310
|
+
bidirectional: false,
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
id: 'represents',
|
|
314
|
+
displayName: 'Represents',
|
|
315
|
+
description: 'Persona represents a user segment from interviews',
|
|
316
|
+
sourceTypes: ['persona'],
|
|
317
|
+
targetTypes: ['interview'],
|
|
318
|
+
bidirectional: false,
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
id: 'tests',
|
|
322
|
+
displayName: 'Tests',
|
|
323
|
+
description: 'Experiment tests a hypothesis',
|
|
324
|
+
sourceTypes: ['experiment'],
|
|
325
|
+
targetTypes: ['hypothesis'],
|
|
326
|
+
bidirectional: false,
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
id: 'informed_by',
|
|
330
|
+
displayName: 'Informed By',
|
|
331
|
+
description: 'Hypothesis informed by an insight',
|
|
332
|
+
sourceTypes: ['hypothesis'],
|
|
333
|
+
targetTypes: ['insight'],
|
|
334
|
+
bidirectional: false,
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
id: 'related',
|
|
338
|
+
displayName: 'Related To',
|
|
339
|
+
description: 'General relationship between any entities',
|
|
340
|
+
sourceTypes: 'any',
|
|
341
|
+
targetTypes: 'any',
|
|
342
|
+
bidirectional: true,
|
|
343
|
+
reverseId: 'related',
|
|
344
|
+
},
|
|
345
|
+
],
|
|
346
|
+
};
|
|
347
|
+
//# sourceMappingURL=ux-research.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ux-research.js","sourceRoot":"","sources":["../../../src/templates/community/ux-research.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 4. Activate the selected template
|
|
9
9
|
* 5. Pre-generate schemas for performance
|
|
10
10
|
*/
|
|
11
|
-
import type { TemplateConfig } from './types.js';
|
|
11
|
+
import type { TemplateConfig, TemplateDefinition } from './types.js';
|
|
12
12
|
/**
|
|
13
13
|
* Find the config.json file.
|
|
14
14
|
*
|
|
@@ -22,10 +22,11 @@ import type { TemplateConfig } from './types.js';
|
|
|
22
22
|
*/
|
|
23
23
|
export declare function findConfigFile(configPath?: string): string | null;
|
|
24
24
|
/**
|
|
25
|
-
* Load template configuration from config.json.
|
|
25
|
+
* Load template configuration from config.json and/or standalone template.json.
|
|
26
26
|
*
|
|
27
27
|
* Searches for config.json in multiple locations and extracts the template
|
|
28
|
-
* section.
|
|
28
|
+
* section. Also checks for standalone template.json in the same directory,
|
|
29
|
+
* which takes precedence over inline template definitions.
|
|
29
30
|
*
|
|
30
31
|
* @param configPath - Optional explicit path to config file
|
|
31
32
|
* @returns Template configuration object
|
|
@@ -44,6 +45,17 @@ export declare function loadTemplateConfig(configPath?: string): TemplateConfig;
|
|
|
44
45
|
* built-in templates can be referenced by ID.
|
|
45
46
|
*/
|
|
46
47
|
export declare function registerBuiltinTemplates(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Register all community-contributed templates.
|
|
50
|
+
*
|
|
51
|
+
* Community templates are registered as 'config' source (not 'builtin')
|
|
52
|
+
* to distinguish them from core templates while still making them available
|
|
53
|
+
* for activation.
|
|
54
|
+
*
|
|
55
|
+
* This function should be called after built-in templates and before user
|
|
56
|
+
* templates so that user templates can override community templates if needed.
|
|
57
|
+
*/
|
|
58
|
+
export declare function registerCommunityTemplates(): void;
|
|
47
59
|
/**
|
|
48
60
|
* Register user-defined templates from config.
|
|
49
61
|
*
|
|
@@ -77,10 +89,11 @@ export declare function pregenerateSchemas(): void;
|
|
|
77
89
|
*
|
|
78
90
|
* Performs complete setup:
|
|
79
91
|
* 1. Register built-in templates
|
|
80
|
-
* 2.
|
|
81
|
-
* 3.
|
|
82
|
-
* 4.
|
|
83
|
-
* 5.
|
|
92
|
+
* 2. Register community templates
|
|
93
|
+
* 3. Load config from file
|
|
94
|
+
* 4. Register user-defined templates
|
|
95
|
+
* 5. Activate selected template
|
|
96
|
+
* 6. Pre-generate schemas
|
|
84
97
|
*
|
|
85
98
|
* This is the main entry point for template system initialization.
|
|
86
99
|
* Call this at application startup before using any template features.
|
|
@@ -97,6 +110,48 @@ export declare function pregenerateSchemas(): void;
|
|
|
97
110
|
* ```
|
|
98
111
|
*/
|
|
99
112
|
export declare function initializeTemplates(configPath?: string): TemplateConfig;
|
|
113
|
+
/**
|
|
114
|
+
* Load a standalone template file from disk.
|
|
115
|
+
*
|
|
116
|
+
* Reads a JSON file containing a template definition and validates it
|
|
117
|
+
* against the TemplateDefinitionSchema.
|
|
118
|
+
*
|
|
119
|
+
* @param filePath - Path to the template JSON file
|
|
120
|
+
* @returns Validated template definition
|
|
121
|
+
* @throws {Error} If file cannot be read or parsed
|
|
122
|
+
* @throws {TemplateValidationError} If template fails validation
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* const template = loadTemplateFile('./template.json');
|
|
127
|
+
* console.log(`Loaded template: ${template.name}`);
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export declare function loadTemplateFile(filePath: string): TemplateDefinition;
|
|
131
|
+
/**
|
|
132
|
+
* Validate a template file without loading it into the registry.
|
|
133
|
+
*
|
|
134
|
+
* Useful for CLI tools and pre-flight validation. Returns the validated
|
|
135
|
+
* template if successful, throws TemplateValidationError with details if not.
|
|
136
|
+
*
|
|
137
|
+
* @param filePath - Path to the template JSON file
|
|
138
|
+
* @returns Validated template definition
|
|
139
|
+
* @throws {Error} If file cannot be read or parsed
|
|
140
|
+
* @throws {TemplateValidationError} If template fails validation
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* try {
|
|
145
|
+
* const template = validateTemplateFile('./template.json');
|
|
146
|
+
* console.log(`Template "${template.name}" is valid!`);
|
|
147
|
+
* } catch (err) {
|
|
148
|
+
* if (err instanceof TemplateValidationError) {
|
|
149
|
+
* console.error(err.toUserMessage());
|
|
150
|
+
* }
|
|
151
|
+
* }
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export declare function validateTemplateFile(filePath: string): TemplateDefinition;
|
|
100
155
|
/**
|
|
101
156
|
* Convenience function to get an entity schema by name.
|
|
102
157
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/templates/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/templates/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AASrE;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoBjE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,cAAc,CAuEtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAOjD;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CASlE;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAE7D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAQzC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,cAAc,CAoBvE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CA2BrE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAEzE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,8DAWrD"}
|
package/dist/templates/loader.js
CHANGED
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
import { readFileSync, existsSync } from 'fs';
|
|
12
12
|
import { resolve, dirname } from 'path';
|
|
13
13
|
import { fileURLToPath } from 'url';
|
|
14
|
-
import { validateTemplateConfig } from './validator.js';
|
|
14
|
+
import { validateTemplateConfig, TemplateDefinitionSchema, TemplateValidationError } from './validator.js';
|
|
15
15
|
import { templateRegistry } from './registry.js';
|
|
16
16
|
import { schemaFactory } from './schema-factory.js';
|
|
17
17
|
import { worldbuildingTemplate } from './builtin/worldbuilding.js';
|
|
18
18
|
import { researchTemplate } from './builtin/research.js';
|
|
19
19
|
import { peopleManagementTemplate } from './builtin/people-management.js';
|
|
20
|
+
import { communityTemplates } from './community/index.js';
|
|
20
21
|
/**
|
|
21
22
|
* Find the config.json file.
|
|
22
23
|
*
|
|
@@ -47,10 +48,11 @@ export function findConfigFile(configPath) {
|
|
|
47
48
|
return null;
|
|
48
49
|
}
|
|
49
50
|
/**
|
|
50
|
-
* Load template configuration from config.json.
|
|
51
|
+
* Load template configuration from config.json and/or standalone template.json.
|
|
51
52
|
*
|
|
52
53
|
* Searches for config.json in multiple locations and extracts the template
|
|
53
|
-
* section.
|
|
54
|
+
* section. Also checks for standalone template.json in the same directory,
|
|
55
|
+
* which takes precedence over inline template definitions.
|
|
54
56
|
*
|
|
55
57
|
* @param configPath - Optional explicit path to config file
|
|
56
58
|
* @returns Template configuration object
|
|
@@ -79,6 +81,39 @@ export function loadTemplateConfig(configPath) {
|
|
|
79
81
|
activeTemplate: 'worldbuilding',
|
|
80
82
|
templates: [],
|
|
81
83
|
};
|
|
84
|
+
// Check for standalone template.json alongside config.json
|
|
85
|
+
const configDir = dirname(configFilePath);
|
|
86
|
+
const standaloneTemplatePath = resolve(configDir, 'template.json');
|
|
87
|
+
if (existsSync(standaloneTemplatePath)) {
|
|
88
|
+
try {
|
|
89
|
+
const standaloneTemplate = loadTemplateFile(standaloneTemplatePath);
|
|
90
|
+
// Ensure templates array exists
|
|
91
|
+
if (!templateConfig.templates) {
|
|
92
|
+
templateConfig.templates = [];
|
|
93
|
+
}
|
|
94
|
+
// Check if template with same ID already exists in config
|
|
95
|
+
const existingIndex = templateConfig.templates.findIndex((t) => t.id === standaloneTemplate.id);
|
|
96
|
+
if (existingIndex >= 0) {
|
|
97
|
+
// Standalone template takes precedence - replace existing
|
|
98
|
+
templateConfig.templates[existingIndex] = standaloneTemplate;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// Add standalone template to the list
|
|
102
|
+
templateConfig.templates.push(standaloneTemplate);
|
|
103
|
+
}
|
|
104
|
+
// If no activeTemplate specified, use the standalone template
|
|
105
|
+
if (!templateConfig.activeTemplate || templateConfig.activeTemplate === 'worldbuilding') {
|
|
106
|
+
templateConfig.activeTemplate = standaloneTemplate.id;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
// If it's a validation error, rethrow with context
|
|
111
|
+
if (err instanceof TemplateValidationError) {
|
|
112
|
+
throw err;
|
|
113
|
+
}
|
|
114
|
+
throw new Error(`Failed to load standalone template.json: ${err instanceof Error ? err.message : String(err)}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
82
117
|
// Validate the template config
|
|
83
118
|
return validateTemplateConfig(templateConfig);
|
|
84
119
|
}
|
|
@@ -98,6 +133,24 @@ export function registerBuiltinTemplates() {
|
|
|
98
133
|
templateRegistry.register(researchTemplate, 'builtin');
|
|
99
134
|
templateRegistry.register(peopleManagementTemplate, 'builtin');
|
|
100
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Register all community-contributed templates.
|
|
138
|
+
*
|
|
139
|
+
* Community templates are registered as 'config' source (not 'builtin')
|
|
140
|
+
* to distinguish them from core templates while still making them available
|
|
141
|
+
* for activation.
|
|
142
|
+
*
|
|
143
|
+
* This function should be called after built-in templates and before user
|
|
144
|
+
* templates so that user templates can override community templates if needed.
|
|
145
|
+
*/
|
|
146
|
+
export function registerCommunityTemplates() {
|
|
147
|
+
for (const template of communityTemplates) {
|
|
148
|
+
// Skip if template with same ID is already registered
|
|
149
|
+
if (!templateRegistry.has(template.id)) {
|
|
150
|
+
templateRegistry.register(template, 'config');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
101
154
|
/**
|
|
102
155
|
* Register user-defined templates from config.
|
|
103
156
|
*
|
|
@@ -148,10 +201,11 @@ export function pregenerateSchemas() {
|
|
|
148
201
|
*
|
|
149
202
|
* Performs complete setup:
|
|
150
203
|
* 1. Register built-in templates
|
|
151
|
-
* 2.
|
|
152
|
-
* 3.
|
|
153
|
-
* 4.
|
|
154
|
-
* 5.
|
|
204
|
+
* 2. Register community templates
|
|
205
|
+
* 3. Load config from file
|
|
206
|
+
* 4. Register user-defined templates
|
|
207
|
+
* 5. Activate selected template
|
|
208
|
+
* 6. Pre-generate schemas
|
|
155
209
|
*
|
|
156
210
|
* This is the main entry point for template system initialization.
|
|
157
211
|
* Call this at application startup before using any template features.
|
|
@@ -170,16 +224,83 @@ export function pregenerateSchemas() {
|
|
|
170
224
|
export function initializeTemplates(configPath) {
|
|
171
225
|
// 1. Register built-in templates
|
|
172
226
|
registerBuiltinTemplates();
|
|
173
|
-
// 2.
|
|
227
|
+
// 2. Register community templates
|
|
228
|
+
registerCommunityTemplates();
|
|
229
|
+
// 3. Load config
|
|
174
230
|
const config = loadTemplateConfig(configPath);
|
|
175
|
-
//
|
|
231
|
+
// 4. Register user templates
|
|
176
232
|
registerUserTemplates(config);
|
|
177
|
-
//
|
|
233
|
+
// 5. Activate selected template
|
|
178
234
|
activateTemplate(config);
|
|
179
|
-
//
|
|
235
|
+
// 6. Pre-generate schemas
|
|
180
236
|
pregenerateSchemas();
|
|
181
237
|
return config;
|
|
182
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Load a standalone template file from disk.
|
|
241
|
+
*
|
|
242
|
+
* Reads a JSON file containing a template definition and validates it
|
|
243
|
+
* against the TemplateDefinitionSchema.
|
|
244
|
+
*
|
|
245
|
+
* @param filePath - Path to the template JSON file
|
|
246
|
+
* @returns Validated template definition
|
|
247
|
+
* @throws {Error} If file cannot be read or parsed
|
|
248
|
+
* @throws {TemplateValidationError} If template fails validation
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* const template = loadTemplateFile('./template.json');
|
|
253
|
+
* console.log(`Loaded template: ${template.name}`);
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
export function loadTemplateFile(filePath) {
|
|
257
|
+
const resolvedPath = resolve(filePath);
|
|
258
|
+
let fileContent;
|
|
259
|
+
try {
|
|
260
|
+
fileContent = readFileSync(resolvedPath, 'utf-8');
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
throw new Error(`Failed to read template file at ${resolvedPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
264
|
+
}
|
|
265
|
+
let templateData;
|
|
266
|
+
try {
|
|
267
|
+
templateData = JSON.parse(fileContent);
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
throw new Error(`Failed to parse template file as JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
271
|
+
}
|
|
272
|
+
const result = TemplateDefinitionSchema.safeParse(templateData);
|
|
273
|
+
if (!result.success) {
|
|
274
|
+
throw new TemplateValidationError('Invalid template definition', result.error.issues);
|
|
275
|
+
}
|
|
276
|
+
return result.data;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Validate a template file without loading it into the registry.
|
|
280
|
+
*
|
|
281
|
+
* Useful for CLI tools and pre-flight validation. Returns the validated
|
|
282
|
+
* template if successful, throws TemplateValidationError with details if not.
|
|
283
|
+
*
|
|
284
|
+
* @param filePath - Path to the template JSON file
|
|
285
|
+
* @returns Validated template definition
|
|
286
|
+
* @throws {Error} If file cannot be read or parsed
|
|
287
|
+
* @throws {TemplateValidationError} If template fails validation
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```ts
|
|
291
|
+
* try {
|
|
292
|
+
* const template = validateTemplateFile('./template.json');
|
|
293
|
+
* console.log(`Template "${template.name}" is valid!`);
|
|
294
|
+
* } catch (err) {
|
|
295
|
+
* if (err instanceof TemplateValidationError) {
|
|
296
|
+
* console.error(err.toUserMessage());
|
|
297
|
+
* }
|
|
298
|
+
* }
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
export function validateTemplateFile(filePath) {
|
|
302
|
+
return loadTemplateFile(filePath);
|
|
303
|
+
}
|
|
183
304
|
/**
|
|
184
305
|
* Convenience function to get an entity schema by name.
|
|
185
306
|
*
|