@hanzo/persona 1.0.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 +68 -0
- package/index.js +36 -0
- package/package.json +40 -0
- package/schemas/persona_schema.yaml +295 -0
- package/schemas/personality.schema.json +228 -0
- package/scripts/add-personality.js +220 -0
- package/scripts/build.js +345 -0
- package/scripts/enhance-scientists.js +215 -0
- package/scripts/enhance_all_personalities.py +926 -0
- package/scripts/migrate.js +384 -0
- package/scripts/parallel-validate.js +322 -0
- package/scripts/split-personalities.js +95 -0
- package/scripts/validate.js +306 -0
- package/tools/unix_tools.yaml +349 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const readline = require('readline');
|
|
6
|
+
|
|
7
|
+
const rl = readline.createInterface({
|
|
8
|
+
input: process.stdin,
|
|
9
|
+
output: process.stdout
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
// Helper to ask questions
|
|
13
|
+
const question = (q) => new Promise(resolve => rl.question(q, resolve));
|
|
14
|
+
|
|
15
|
+
// Categories and their directories
|
|
16
|
+
const CATEGORIES = {
|
|
17
|
+
programmer: 'programmers',
|
|
18
|
+
philosopher: 'philosophers',
|
|
19
|
+
scientist: 'scientists',
|
|
20
|
+
religious: 'religious',
|
|
21
|
+
revolutionary: 'revolutionaries',
|
|
22
|
+
writer: 'writers',
|
|
23
|
+
artist: 'artists',
|
|
24
|
+
architect: 'architects',
|
|
25
|
+
athlete: 'athletes',
|
|
26
|
+
explorer: 'explorers',
|
|
27
|
+
activist: 'activists',
|
|
28
|
+
tech_leader: 'leaders',
|
|
29
|
+
leader: 'leaders',
|
|
30
|
+
pioneer: 'pioneers',
|
|
31
|
+
special: 'special'
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Generate ID from name
|
|
35
|
+
function generateId(name) {
|
|
36
|
+
return name
|
|
37
|
+
.toLowerCase()
|
|
38
|
+
.replace(/[^a-z0-9\s-]/g, '')
|
|
39
|
+
.replace(/\s+/g, '_')
|
|
40
|
+
.replace(/-+/g, '_')
|
|
41
|
+
.substring(0, 50);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Main function
|
|
45
|
+
async function addPersonality() {
|
|
46
|
+
console.log('\n=== Add New Personality ===\n');
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
// Basic info
|
|
50
|
+
const name = await question('Name (display name): ');
|
|
51
|
+
const fullName = await question('Full name (optional, press Enter to skip): ');
|
|
52
|
+
const id = await question(`ID (press Enter for "${generateId(name)}"): `) || generateId(name);
|
|
53
|
+
|
|
54
|
+
// Category
|
|
55
|
+
console.log('\nCategories:', Object.keys(CATEGORIES).join(', '));
|
|
56
|
+
const category = await question('Category: ');
|
|
57
|
+
|
|
58
|
+
if (!CATEGORIES[category]) {
|
|
59
|
+
console.error(`Invalid category: ${category}`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Tags
|
|
64
|
+
const tagsInput = await question('Tags (comma-separated, optional): ');
|
|
65
|
+
const tags = tagsInput ? tagsInput.split(',').map(t => t.trim()).filter(Boolean) : [];
|
|
66
|
+
|
|
67
|
+
// OCEAN scores
|
|
68
|
+
console.log('\n=== OCEAN Scores (0-100) ===');
|
|
69
|
+
const openness = parseInt(await question('Openness (creativity, curiosity): ')) || 50;
|
|
70
|
+
const conscientiousness = parseInt(await question('Conscientiousness (organization, discipline): ')) || 50;
|
|
71
|
+
const extraversion = parseInt(await question('Extraversion (sociability, energy): ')) || 50;
|
|
72
|
+
const agreeableness = parseInt(await question('Agreeableness (cooperation, trust): ')) || 50;
|
|
73
|
+
const neuroticism = parseInt(await question('Neuroticism (emotional instability): ')) || 50;
|
|
74
|
+
|
|
75
|
+
// Personality
|
|
76
|
+
console.log('\n=== Personality ===');
|
|
77
|
+
const summary = await question('Summary (brief description): ');
|
|
78
|
+
const philosophy = await question('Philosophy (core belief/motto): ');
|
|
79
|
+
const approach = await question('Approach (optional): ');
|
|
80
|
+
const communication = await question('Communication style (optional): ');
|
|
81
|
+
|
|
82
|
+
// Values
|
|
83
|
+
const valuesInput = await question('Core values (comma-separated, optional): ');
|
|
84
|
+
const values = valuesInput ? valuesInput.split(',').map(v => v.trim()).filter(Boolean) : undefined;
|
|
85
|
+
|
|
86
|
+
// Quotes
|
|
87
|
+
console.log('\n=== Quotes (optional, enter empty line to finish) ===');
|
|
88
|
+
const quotes = [];
|
|
89
|
+
let quoteNum = 1;
|
|
90
|
+
while (true) {
|
|
91
|
+
const quote = await question(`Quote ${quoteNum}: `);
|
|
92
|
+
if (!quote) break;
|
|
93
|
+
quotes.push(quote);
|
|
94
|
+
quoteNum++;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// For programmers, add technical info
|
|
98
|
+
let technical;
|
|
99
|
+
if (category === 'programmer' || category === 'tech_leader') {
|
|
100
|
+
console.log('\n=== Technical Info (optional) ===');
|
|
101
|
+
const languagesInput = await question('Programming languages (comma-separated): ');
|
|
102
|
+
const languages = languagesInput ? languagesInput.split(',').map(l => l.trim()).filter(Boolean) : undefined;
|
|
103
|
+
|
|
104
|
+
const domainsInput = await question('Domains (comma-separated): ');
|
|
105
|
+
const domains = domainsInput ? domainsInput.split(',').map(d => d.trim()).filter(Boolean) : undefined;
|
|
106
|
+
|
|
107
|
+
const essentialTools = await question('Essential tools (comma-separated): ');
|
|
108
|
+
const essential = essentialTools ? essentialTools.split(',').map(t => t.trim()).filter(Boolean) : undefined;
|
|
109
|
+
|
|
110
|
+
if (languages || domains || essential) {
|
|
111
|
+
technical = {};
|
|
112
|
+
if (languages) technical.languages = languages;
|
|
113
|
+
if (domains) technical.domains = domains;
|
|
114
|
+
if (essential) technical.tools = { essential };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Build the personality object
|
|
119
|
+
const personality = {
|
|
120
|
+
"$schema": "../schemas/personality.schema.json",
|
|
121
|
+
id,
|
|
122
|
+
name,
|
|
123
|
+
category
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
if (fullName) personality.fullName = fullName;
|
|
127
|
+
if (tags.length > 0) personality.tags = tags;
|
|
128
|
+
|
|
129
|
+
personality.ocean = {
|
|
130
|
+
openness: Math.min(100, Math.max(0, openness)),
|
|
131
|
+
conscientiousness: Math.min(100, Math.max(0, conscientiousness)),
|
|
132
|
+
extraversion: Math.min(100, Math.max(0, extraversion)),
|
|
133
|
+
agreeableness: Math.min(100, Math.max(0, agreeableness)),
|
|
134
|
+
neuroticism: Math.min(100, Math.max(0, neuroticism))
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
personality.personality = {
|
|
138
|
+
summary: summary || `${category} personality`,
|
|
139
|
+
philosophy: philosophy || 'No philosophy recorded'
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
if (approach) personality.personality.approach = approach;
|
|
143
|
+
if (communication) personality.personality.communication = communication;
|
|
144
|
+
if (values) personality.personality.values = values;
|
|
145
|
+
if (technical) personality.technical = technical;
|
|
146
|
+
if (quotes.length > 0) personality.quotes = quotes;
|
|
147
|
+
|
|
148
|
+
// Determine target directory
|
|
149
|
+
const targetDir = CATEGORIES[category];
|
|
150
|
+
const baseDir = path.join(__dirname, '..', 'personalities_v2');
|
|
151
|
+
const dirPath = path.join(baseDir, targetDir);
|
|
152
|
+
|
|
153
|
+
// Ensure directory exists
|
|
154
|
+
if (!fs.existsSync(dirPath)) {
|
|
155
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Check if file already exists
|
|
159
|
+
const filePath = path.join(dirPath, `${id}.json`);
|
|
160
|
+
if (fs.existsSync(filePath)) {
|
|
161
|
+
const overwrite = await question(`\nFile ${id}.json already exists. Overwrite? (y/N): `);
|
|
162
|
+
if (overwrite.toLowerCase() !== 'y') {
|
|
163
|
+
console.log('Cancelled.');
|
|
164
|
+
process.exit(0);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Write the file
|
|
169
|
+
fs.writeFileSync(filePath, JSON.stringify(personality, null, 2));
|
|
170
|
+
console.log(`\n✅ Created: ${targetDir}/${id}.json`);
|
|
171
|
+
|
|
172
|
+
// Update manifest
|
|
173
|
+
const manifestPath = path.join(baseDir, 'index', 'manifest.json');
|
|
174
|
+
if (fs.existsSync(manifestPath)) {
|
|
175
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
176
|
+
|
|
177
|
+
// Update index
|
|
178
|
+
manifest.index[id] = {
|
|
179
|
+
path: `${targetDir}/${id}.json`,
|
|
180
|
+
name: name,
|
|
181
|
+
category: category,
|
|
182
|
+
tags: tags
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// Update category
|
|
186
|
+
if (!manifest.categories[category]) {
|
|
187
|
+
manifest.categories[category] = {
|
|
188
|
+
count: 0,
|
|
189
|
+
path: targetDir,
|
|
190
|
+
ids: []
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!manifest.categories[category].ids.includes(id)) {
|
|
195
|
+
manifest.categories[category].ids.push(id);
|
|
196
|
+
manifest.categories[category].count++;
|
|
197
|
+
manifest.total++;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
201
|
+
console.log('✅ Updated manifest.json');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Suggest rebuilding
|
|
205
|
+
console.log('\nTo rebuild aggregated files, run: npm run build');
|
|
206
|
+
|
|
207
|
+
} catch (err) {
|
|
208
|
+
console.error('\nError:', err.message);
|
|
209
|
+
process.exit(1);
|
|
210
|
+
} finally {
|
|
211
|
+
rl.close();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Run if called directly
|
|
216
|
+
if (require.main === module) {
|
|
217
|
+
addPersonality();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
module.exports = { addPersonality };
|
package/scripts/build.js
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// Configuration
|
|
7
|
+
const PERSONAS_DIR = path.join(__dirname, '..', 'personalities_v2');
|
|
8
|
+
const DIST_DIR = path.join(PERSONAS_DIR, 'dist');
|
|
9
|
+
const INDEX_FILE = path.join(PERSONAS_DIR, 'index', 'manifest.json');
|
|
10
|
+
|
|
11
|
+
// Category mappings (reverse of migrate.js)
|
|
12
|
+
const CATEGORY_DIRS = {
|
|
13
|
+
programmers: ['programmer', 'systems', 'language-creator', 'gaming', 'blockchain'],
|
|
14
|
+
philosophers: ['philosopher'],
|
|
15
|
+
scientists: ['scientist', 'mathematician'],
|
|
16
|
+
religious: ['religious'],
|
|
17
|
+
revolutionaries: ['revolutionary'],
|
|
18
|
+
writers: ['writer', 'poet', 'historian'],
|
|
19
|
+
artists: ['artist', 'musician', 'filmmaker', 'comedian', 'composer'],
|
|
20
|
+
architects: ['architect'],
|
|
21
|
+
athletes: ['athlete'],
|
|
22
|
+
explorers: ['explorer'],
|
|
23
|
+
activists: ['activist'],
|
|
24
|
+
leaders: ['tech_leader', 'leader', 'statesman', 'media'],
|
|
25
|
+
pioneers: ['pioneer'],
|
|
26
|
+
special: ['special', 'master']
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Load all personalities from a directory
|
|
30
|
+
function loadPersonalities(dirPath) {
|
|
31
|
+
const personalities = [];
|
|
32
|
+
|
|
33
|
+
if (!fs.existsSync(dirPath)) {
|
|
34
|
+
return personalities;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.json'));
|
|
38
|
+
|
|
39
|
+
files.forEach(file => {
|
|
40
|
+
try {
|
|
41
|
+
const content = fs.readFileSync(path.join(dirPath, file), 'utf8');
|
|
42
|
+
const personality = JSON.parse(content);
|
|
43
|
+
// Remove the schema reference for the aggregated files
|
|
44
|
+
delete personality.$schema;
|
|
45
|
+
personalities.push(personality);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.error(`Error loading ${file}: ${err.message}`);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return personalities;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Build all personalities file
|
|
55
|
+
function buildAllPersonalities() {
|
|
56
|
+
console.log('Building all personalities file...');
|
|
57
|
+
|
|
58
|
+
const allPersonalities = [];
|
|
59
|
+
const dirs = fs.readdirSync(PERSONAS_DIR)
|
|
60
|
+
.filter(d => !['dist', 'index', 'schemas', 'scripts'].includes(d))
|
|
61
|
+
.filter(d => fs.statSync(path.join(PERSONAS_DIR, d)).isDirectory());
|
|
62
|
+
|
|
63
|
+
dirs.forEach(dir => {
|
|
64
|
+
const personalities = loadPersonalities(path.join(PERSONAS_DIR, dir));
|
|
65
|
+
allPersonalities.push(...personalities);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Sort by name
|
|
69
|
+
allPersonalities.sort((a, b) => a.name.localeCompare(b.name));
|
|
70
|
+
|
|
71
|
+
// Write the file
|
|
72
|
+
const outputPath = path.join(DIST_DIR, 'all.json');
|
|
73
|
+
fs.writeFileSync(outputPath, JSON.stringify({
|
|
74
|
+
version: '2.0.0',
|
|
75
|
+
generated: new Date().toISOString(),
|
|
76
|
+
total: allPersonalities.length,
|
|
77
|
+
personalities: allPersonalities
|
|
78
|
+
}, null, 2));
|
|
79
|
+
|
|
80
|
+
console.log(` Created: dist/all.json (${allPersonalities.length} personalities)`);
|
|
81
|
+
|
|
82
|
+
return allPersonalities;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Build category-specific files
|
|
86
|
+
function buildCategoryFiles() {
|
|
87
|
+
console.log('\nBuilding category files...');
|
|
88
|
+
|
|
89
|
+
const categoryDir = path.join(DIST_DIR, 'by-category');
|
|
90
|
+
if (!fs.existsSync(categoryDir)) {
|
|
91
|
+
fs.mkdirSync(categoryDir, { recursive: true });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
Object.entries(CATEGORY_DIRS).forEach(([dirName, categories]) => {
|
|
95
|
+
const dirPath = path.join(PERSONAS_DIR, dirName);
|
|
96
|
+
const personalities = loadPersonalities(dirPath);
|
|
97
|
+
|
|
98
|
+
if (personalities.length > 0) {
|
|
99
|
+
const outputPath = path.join(categoryDir, `${dirName}.json`);
|
|
100
|
+
fs.writeFileSync(outputPath, JSON.stringify({
|
|
101
|
+
version: '2.0.0',
|
|
102
|
+
generated: new Date().toISOString(),
|
|
103
|
+
category: dirName,
|
|
104
|
+
categories: categories,
|
|
105
|
+
total: personalities.length,
|
|
106
|
+
personalities: personalities
|
|
107
|
+
}, null, 2));
|
|
108
|
+
|
|
109
|
+
console.log(` Created: dist/by-category/${dirName}.json (${personalities.length} personalities)`);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Build tag-based collections
|
|
115
|
+
function buildTagFiles(allPersonalities) {
|
|
116
|
+
console.log('\nBuilding tag files...');
|
|
117
|
+
|
|
118
|
+
const tagDir = path.join(DIST_DIR, 'by-tag');
|
|
119
|
+
if (!fs.existsSync(tagDir)) {
|
|
120
|
+
fs.mkdirSync(tagDir, { recursive: true });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Collect all tags
|
|
124
|
+
const tagMap = new Map();
|
|
125
|
+
|
|
126
|
+
allPersonalities.forEach(p => {
|
|
127
|
+
if (p.tags && Array.isArray(p.tags)) {
|
|
128
|
+
p.tags.forEach(tag => {
|
|
129
|
+
if (!tagMap.has(tag)) {
|
|
130
|
+
tagMap.set(tag, []);
|
|
131
|
+
}
|
|
132
|
+
tagMap.get(tag).push(p);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Write files for tags with 3+ personalities
|
|
138
|
+
let tagCount = 0;
|
|
139
|
+
tagMap.forEach((personalities, tag) => {
|
|
140
|
+
if (personalities.length >= 3) {
|
|
141
|
+
const sanitizedTag = tag.replace(/[^a-z0-9_-]/gi, '_');
|
|
142
|
+
const outputPath = path.join(tagDir, `${sanitizedTag}.json`);
|
|
143
|
+
|
|
144
|
+
fs.writeFileSync(outputPath, JSON.stringify({
|
|
145
|
+
version: '2.0.0',
|
|
146
|
+
generated: new Date().toISOString(),
|
|
147
|
+
tag: tag,
|
|
148
|
+
total: personalities.length,
|
|
149
|
+
personalities: personalities
|
|
150
|
+
}, null, 2));
|
|
151
|
+
|
|
152
|
+
tagCount++;
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
console.log(` Created ${tagCount} tag files (tags with 3+ personalities)`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Generate TypeScript types
|
|
160
|
+
function generateTypes(allPersonalities) {
|
|
161
|
+
console.log('\nGenerating TypeScript types...');
|
|
162
|
+
|
|
163
|
+
const types = `// Auto-generated TypeScript types for personalities
|
|
164
|
+
// Generated: ${new Date().toISOString()}
|
|
165
|
+
|
|
166
|
+
export interface OceanScores {
|
|
167
|
+
openness: number;
|
|
168
|
+
conscientiousness: number;
|
|
169
|
+
extraversion: number;
|
|
170
|
+
agreeableness: number;
|
|
171
|
+
neuroticism: number;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface PersonalityMetadata {
|
|
175
|
+
born?: string;
|
|
176
|
+
died?: string;
|
|
177
|
+
nationality?: string;
|
|
178
|
+
active?: boolean;
|
|
179
|
+
company?: string;
|
|
180
|
+
achievements?: string[];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface PersonalityInfo {
|
|
184
|
+
summary: string;
|
|
185
|
+
philosophy: string;
|
|
186
|
+
approach?: string;
|
|
187
|
+
communication?: string;
|
|
188
|
+
values?: string[];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface TechnicalInfo {
|
|
192
|
+
languages?: string[];
|
|
193
|
+
domains?: string[];
|
|
194
|
+
tools?: {
|
|
195
|
+
essential?: string[];
|
|
196
|
+
preferred?: string[];
|
|
197
|
+
created?: string[];
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface BehavioralTraits {
|
|
202
|
+
codeStyle?: string;
|
|
203
|
+
reviewStyle?: string;
|
|
204
|
+
workStyle?: string;
|
|
205
|
+
collaboration?: string;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export interface Personality {
|
|
209
|
+
id: string;
|
|
210
|
+
name: string;
|
|
211
|
+
fullName?: string;
|
|
212
|
+
category: string;
|
|
213
|
+
subcategory?: string;
|
|
214
|
+
tags?: string[];
|
|
215
|
+
metadata?: PersonalityMetadata;
|
|
216
|
+
ocean: OceanScores;
|
|
217
|
+
personality: PersonalityInfo;
|
|
218
|
+
technical?: TechnicalInfo;
|
|
219
|
+
quotes?: string[];
|
|
220
|
+
behavioral?: BehavioralTraits;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export interface PersonalityCollection {
|
|
224
|
+
version: string;
|
|
225
|
+
generated: string;
|
|
226
|
+
total: number;
|
|
227
|
+
personalities: Personality[];
|
|
228
|
+
category?: string;
|
|
229
|
+
tag?: string;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Personality ID union type
|
|
233
|
+
export type PersonalityId = ${allPersonalities.map(p => `'${p.id}'`).join(' | ')};
|
|
234
|
+
|
|
235
|
+
// Category union type
|
|
236
|
+
export type PersonalityCategory = ${[...new Set(allPersonalities.map(p => `'${p.category}'`))].join(' | ')};
|
|
237
|
+
`;
|
|
238
|
+
|
|
239
|
+
const outputPath = path.join(DIST_DIR, 'types.ts');
|
|
240
|
+
fs.writeFileSync(outputPath, types);
|
|
241
|
+
console.log(' Created: dist/types.ts');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Generate index file for easy imports
|
|
245
|
+
function generateIndex() {
|
|
246
|
+
console.log('\nGenerating index file...');
|
|
247
|
+
|
|
248
|
+
const indexContent = `// Auto-generated index for personality imports
|
|
249
|
+
// Generated: ${new Date().toISOString()}
|
|
250
|
+
|
|
251
|
+
// Individual personality imports
|
|
252
|
+
${Object.entries(CATEGORY_DIRS).map(([dir, cats]) => {
|
|
253
|
+
const dirPath = path.join(PERSONAS_DIR, dir);
|
|
254
|
+
if (!fs.existsSync(dirPath)) return '';
|
|
255
|
+
|
|
256
|
+
const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.json'));
|
|
257
|
+
return files.map(f => {
|
|
258
|
+
const id = f.replace('.json', '');
|
|
259
|
+
return `export { default as ${id} } from '../${dir}/${f}';`;
|
|
260
|
+
}).join('\n');
|
|
261
|
+
}).filter(Boolean).join('\n')}
|
|
262
|
+
|
|
263
|
+
// Category collections
|
|
264
|
+
export { default as allPersonalities } from './all.json';
|
|
265
|
+
${Object.keys(CATEGORY_DIRS).map(dir =>
|
|
266
|
+
`export { default as ${dir} } from './by-category/${dir}.json';`
|
|
267
|
+
).join('\n')}
|
|
268
|
+
|
|
269
|
+
// Type exports
|
|
270
|
+
export * from './types';
|
|
271
|
+
`;
|
|
272
|
+
|
|
273
|
+
const outputPath = path.join(DIST_DIR, 'index.js');
|
|
274
|
+
fs.writeFileSync(outputPath, indexContent);
|
|
275
|
+
console.log(' Created: dist/index.js');
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Update package.json exports
|
|
279
|
+
function updatePackageJson() {
|
|
280
|
+
console.log('\nUpdating package.json exports...');
|
|
281
|
+
|
|
282
|
+
const packagePath = path.join(__dirname, '..', 'package.json');
|
|
283
|
+
if (!fs.existsSync(packagePath)) {
|
|
284
|
+
console.log(' No package.json found, skipping...');
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
try {
|
|
289
|
+
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
290
|
+
|
|
291
|
+
// Add exports field for modern module resolution
|
|
292
|
+
pkg.exports = {
|
|
293
|
+
'.': './personalities_v2/dist/index.js',
|
|
294
|
+
'./all': './personalities_v2/dist/all.json',
|
|
295
|
+
'./types': './personalities_v2/dist/types.ts',
|
|
296
|
+
'./by-category/*': './personalities_v2/dist/by-category/*.json',
|
|
297
|
+
'./by-tag/*': './personalities_v2/dist/by-tag/*.json',
|
|
298
|
+
'./personalities/*': './personalities_v2/*/*.json'
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// Add files field to include in npm package
|
|
302
|
+
pkg.files = [
|
|
303
|
+
'personalities_v2/**/*.json',
|
|
304
|
+
'personalities_v2/dist/**/*',
|
|
305
|
+
'personalities_v2/schemas/*.json',
|
|
306
|
+
'!personalities_v2/scripts'
|
|
307
|
+
];
|
|
308
|
+
|
|
309
|
+
fs.writeFileSync(packagePath, JSON.stringify(pkg, null, 2));
|
|
310
|
+
console.log(' Updated package.json with exports field');
|
|
311
|
+
} catch (err) {
|
|
312
|
+
console.error(` Error updating package.json: ${err.message}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Main build function
|
|
317
|
+
async function build() {
|
|
318
|
+
console.log('Starting build process...\n');
|
|
319
|
+
|
|
320
|
+
// Ensure dist directories exist
|
|
321
|
+
if (!fs.existsSync(DIST_DIR)) {
|
|
322
|
+
fs.mkdirSync(DIST_DIR, { recursive: true });
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Build all files
|
|
326
|
+
const allPersonalities = buildAllPersonalities();
|
|
327
|
+
buildCategoryFiles();
|
|
328
|
+
buildTagFiles(allPersonalities);
|
|
329
|
+
generateTypes(allPersonalities);
|
|
330
|
+
generateIndex();
|
|
331
|
+
updatePackageJson();
|
|
332
|
+
|
|
333
|
+
console.log('\nBuild complete!');
|
|
334
|
+
console.log(`Total personalities: ${allPersonalities.length}`);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Run build
|
|
338
|
+
if (require.main === module) {
|
|
339
|
+
build().catch(err => {
|
|
340
|
+
console.error('Build failed:', err);
|
|
341
|
+
process.exit(1);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
module.exports = { build };
|