@pennyfarthing/shared 7.5.0 → 9.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.
- package/dist/browser.d.ts +6 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +8 -0
- package/dist/browser.js.map +1 -0
- package/dist/generate-skill-docs.d.ts +35 -0
- package/dist/generate-skill-docs.d.ts.map +1 -0
- package/dist/generate-skill-docs.js +442 -0
- package/dist/generate-skill-docs.js.map +1 -0
- package/dist/generate-skill-docs.test.d.ts +13 -0
- package/dist/generate-skill-docs.test.d.ts.map +1 -0
- package/dist/generate-skill-docs.test.js +519 -0
- package/dist/generate-skill-docs.test.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/marker/constants.d.ts +39 -0
- package/dist/marker/constants.d.ts.map +1 -0
- package/dist/marker/constants.js +46 -0
- package/dist/marker/constants.js.map +1 -0
- package/dist/marker/continue.test.d.ts +12 -0
- package/dist/marker/continue.test.d.ts.map +1 -0
- package/dist/marker/continue.test.js +76 -0
- package/dist/marker/continue.test.js.map +1 -0
- package/dist/marker/detect.d.ts +25 -0
- package/dist/marker/detect.d.ts.map +1 -0
- package/dist/marker/detect.js +53 -0
- package/dist/marker/detect.js.map +1 -0
- package/dist/marker/detect.test.d.ts +10 -0
- package/dist/marker/detect.test.d.ts.map +1 -0
- package/dist/marker/detect.test.js +418 -0
- package/dist/marker/detect.test.js.map +1 -0
- package/dist/marker/index.d.ts +14 -0
- package/dist/marker/index.d.ts.map +1 -0
- package/dist/marker/index.js +15 -0
- package/dist/marker/index.js.map +1 -0
- package/dist/marker/strip.d.ts +26 -0
- package/dist/marker/strip.d.ts.map +1 -0
- package/dist/marker/strip.js +39 -0
- package/dist/marker/strip.js.map +1 -0
- package/dist/marker/types.d.ts +23 -0
- package/dist/marker/types.d.ts.map +1 -0
- package/dist/marker/types.js +7 -0
- package/dist/marker/types.js.map +1 -0
- package/dist/migrate-theme-schema.test.d.ts +8 -0
- package/dist/migrate-theme-schema.test.d.ts.map +1 -0
- package/dist/migrate-theme-schema.test.js +100 -0
- package/dist/migrate-theme-schema.test.js.map +1 -0
- package/dist/portrait-resolver.d.ts +32 -0
- package/dist/portrait-resolver.d.ts.map +1 -0
- package/dist/portrait-resolver.js +225 -0
- package/dist/portrait-resolver.js.map +1 -0
- package/dist/portrait-resolver.test.d.ts +2 -0
- package/dist/portrait-resolver.test.d.ts.map +1 -0
- package/dist/portrait-resolver.test.js +156 -0
- package/dist/portrait-resolver.test.js.map +1 -0
- package/dist/skill-search.d.ts +36 -0
- package/dist/skill-search.d.ts.map +1 -0
- package/dist/skill-search.js +300 -0
- package/dist/skill-search.js.map +1 -0
- package/dist/skill-search.sh +41 -0
- package/dist/skill-search.test.d.ts +16 -0
- package/dist/skill-search.test.d.ts.map +1 -0
- package/dist/skill-search.test.js +177 -0
- package/dist/skill-search.test.js.map +1 -0
- package/dist/skill-suggest.d.ts +76 -0
- package/dist/skill-suggest.d.ts.map +1 -0
- package/dist/skill-suggest.js +256 -0
- package/dist/skill-suggest.js.map +1 -0
- package/dist/skill-suggest.test.d.ts +12 -0
- package/dist/skill-suggest.test.d.ts.map +1 -0
- package/dist/skill-suggest.test.js +257 -0
- package/dist/skill-suggest.test.js.map +1 -0
- package/dist/theme-loader.d.ts +81 -0
- package/dist/theme-loader.d.ts.map +1 -0
- package/dist/theme-loader.js +491 -0
- package/dist/theme-loader.js.map +1 -0
- package/dist/theme-loader.test.d.ts +8 -0
- package/dist/theme-loader.test.d.ts.map +1 -0
- package/dist/theme-loader.test.js +62 -0
- package/dist/theme-loader.test.js.map +1 -0
- package/package.json +14 -1
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Loader - Unified theme discovery, loading, and metadata for Pennyfarthing
|
|
3
|
+
*
|
|
4
|
+
* This is the ONE canonical implementation of theme loading. All other packages
|
|
5
|
+
* (core CLI, cyclist, Python scripts, bash scripts) should delegate here.
|
|
6
|
+
*
|
|
7
|
+
* Discovery algorithm (checked in order, deduped by theme ID):
|
|
8
|
+
* 1. Core themes: resolvePennyfarthingDist()/personas/themes/
|
|
9
|
+
* 2. Theme packages: node_modules/@pennyfarthing/themes-* /themes/
|
|
10
|
+
* 3. Project custom: {projectRoot}/.claude/pennyfarthing/themes/
|
|
11
|
+
* 4. User custom: ~/.claude/pennyfarthing/themes/
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
14
|
+
import { join, basename, dirname } from 'node:path';
|
|
15
|
+
import { homedir } from 'node:os';
|
|
16
|
+
import { parse as parseYaml } from 'yaml';
|
|
17
|
+
import { resolvePennyfarthingDist, getPortraitPaths } from './portrait-resolver.js';
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Category mapping (moved from packages/cyclist/src/theme-metadata.ts)
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
export const CATEGORY_MAP = {
|
|
22
|
+
// TV Series
|
|
23
|
+
'star-trek-tos': 'TV Series',
|
|
24
|
+
'star-trek-tng': 'TV Series',
|
|
25
|
+
'star-trek-ds9': 'TV Series',
|
|
26
|
+
'star-trek-voyager': 'TV Series',
|
|
27
|
+
'breaking-bad': 'TV Series',
|
|
28
|
+
'the-office': 'TV Series',
|
|
29
|
+
'the-wire': 'TV Series',
|
|
30
|
+
'game-of-thrones': 'TV Series',
|
|
31
|
+
'ted-lasso': 'TV Series',
|
|
32
|
+
'parks-and-recreation': 'TV Series',
|
|
33
|
+
'friends': 'TV Series',
|
|
34
|
+
'seinfeld': 'TV Series',
|
|
35
|
+
'mad-men': 'TV Series',
|
|
36
|
+
'the-sopranos': 'TV Series',
|
|
37
|
+
'arrested-development': 'TV Series',
|
|
38
|
+
'schitts-creek': 'TV Series',
|
|
39
|
+
'brooklyn-nine-nine': 'TV Series',
|
|
40
|
+
'firefly': 'TV Series',
|
|
41
|
+
'battlestar-galactica': 'TV Series',
|
|
42
|
+
'doctor-who': 'TV Series',
|
|
43
|
+
'stranger-things': 'TV Series',
|
|
44
|
+
'the-good-place': 'TV Series',
|
|
45
|
+
'its-always-sunny': 'TV Series',
|
|
46
|
+
'downton-abbey': 'TV Series',
|
|
47
|
+
'the-crown': 'TV Series',
|
|
48
|
+
'succession': 'TV Series',
|
|
49
|
+
'the-simpsons': 'TV Series',
|
|
50
|
+
'futurama': 'TV Series',
|
|
51
|
+
'arcane': 'TV Series',
|
|
52
|
+
'avatar-the-last-airbender': 'TV Series',
|
|
53
|
+
'severance': 'TV Series',
|
|
54
|
+
'the-west-wing': 'TV Series',
|
|
55
|
+
'lost': 'TV Series',
|
|
56
|
+
'the-x-files': 'TV Series',
|
|
57
|
+
'twin-peaks': 'TV Series',
|
|
58
|
+
'the-twilight-zone': 'TV Series',
|
|
59
|
+
'mash': 'TV Series',
|
|
60
|
+
'a-team': 'TV Series',
|
|
61
|
+
// Literature
|
|
62
|
+
'alice-in-wonderland': 'Literature',
|
|
63
|
+
'lord-of-the-rings': 'Literature',
|
|
64
|
+
'discworld': 'Literature',
|
|
65
|
+
'hitchhikers-guide': 'Literature',
|
|
66
|
+
'dune': 'Literature',
|
|
67
|
+
'pride-and-prejudice': 'Literature',
|
|
68
|
+
'sherlock-holmes': 'Literature',
|
|
69
|
+
'harry-potter': 'Literature',
|
|
70
|
+
'narnia': 'Literature',
|
|
71
|
+
'foundation': 'Literature',
|
|
72
|
+
'wheel-of-time': 'Literature',
|
|
73
|
+
'stormlight-archive': 'Literature',
|
|
74
|
+
'mistborn': 'Literature',
|
|
75
|
+
'good-omens': 'Literature',
|
|
76
|
+
'american-gods': 'Literature',
|
|
77
|
+
'the-expanse': 'Literature',
|
|
78
|
+
'enders-game': 'Literature',
|
|
79
|
+
'three-body-problem': 'Literature',
|
|
80
|
+
'hyperion': 'Literature',
|
|
81
|
+
'1984': 'Literature',
|
|
82
|
+
'brave-new-world': 'Literature',
|
|
83
|
+
'frankenstein': 'Literature',
|
|
84
|
+
'dracula': 'Literature',
|
|
85
|
+
'moby-dick': 'Literature',
|
|
86
|
+
'odyssey': 'Literature',
|
|
87
|
+
'iliad': 'Literature',
|
|
88
|
+
'don-quixote': 'Literature',
|
|
89
|
+
'count-of-monte-cristo': 'Literature',
|
|
90
|
+
'les-miserables': 'Literature',
|
|
91
|
+
'great-gatsby': 'Literature',
|
|
92
|
+
'winnie-the-pooh': 'Literature',
|
|
93
|
+
'peter-pan': 'Literature',
|
|
94
|
+
'wizard-of-oz': 'Literature',
|
|
95
|
+
// Film
|
|
96
|
+
'star-wars': 'Film',
|
|
97
|
+
'matrix': 'Film',
|
|
98
|
+
'inception': 'Film',
|
|
99
|
+
'pulp-fiction': 'Film',
|
|
100
|
+
'godfather': 'Film',
|
|
101
|
+
'shawshank-redemption': 'Film',
|
|
102
|
+
'fight-club': 'Film',
|
|
103
|
+
'blade-runner': 'Film',
|
|
104
|
+
'back-to-the-future': 'Film',
|
|
105
|
+
'jurassic-park': 'Film',
|
|
106
|
+
'indiana-jones': 'Film',
|
|
107
|
+
'marvel-avengers': 'Film',
|
|
108
|
+
'guardians-of-the-galaxy': 'Film',
|
|
109
|
+
'pirates-of-the-caribbean': 'Film',
|
|
110
|
+
'princess-bride': 'Film',
|
|
111
|
+
'monty-python': 'Film',
|
|
112
|
+
'ghostbusters': 'Film',
|
|
113
|
+
'men-in-black': 'Film',
|
|
114
|
+
'ocean-eleven': 'Film',
|
|
115
|
+
'big-lebowski': 'Film',
|
|
116
|
+
'grand-budapest-hotel': 'Film',
|
|
117
|
+
'kill-bill': 'Film',
|
|
118
|
+
'john-wick': 'Film',
|
|
119
|
+
'die-hard': 'Film',
|
|
120
|
+
'terminator': 'Film',
|
|
121
|
+
'alien': 'Film',
|
|
122
|
+
'predator': 'Film',
|
|
123
|
+
'mad-max': 'Film',
|
|
124
|
+
'studio-ghibli': 'Film',
|
|
125
|
+
'pixar': 'Film',
|
|
126
|
+
'disney-classics': 'Film',
|
|
127
|
+
'interstellar': 'Film',
|
|
128
|
+
'arrival': 'Film',
|
|
129
|
+
'her': 'Film',
|
|
130
|
+
'ex-machina': 'Film',
|
|
131
|
+
// Mythology
|
|
132
|
+
'greek-mythology': 'Mythology',
|
|
133
|
+
'norse-mythology': 'Mythology',
|
|
134
|
+
'egyptian-mythology': 'Mythology',
|
|
135
|
+
'celtic-mythology': 'Mythology',
|
|
136
|
+
'japanese-mythology': 'Mythology',
|
|
137
|
+
'hindu-mythology': 'Mythology',
|
|
138
|
+
'arthurian-legend': 'Mythology',
|
|
139
|
+
// Games
|
|
140
|
+
'zelda': 'Games',
|
|
141
|
+
'mario': 'Games',
|
|
142
|
+
'final-fantasy': 'Games',
|
|
143
|
+
'mass-effect': 'Games',
|
|
144
|
+
'bioshock': 'Games',
|
|
145
|
+
'portal': 'Games',
|
|
146
|
+
'half-life': 'Games',
|
|
147
|
+
'halo': 'Games',
|
|
148
|
+
'overwatch': 'Games',
|
|
149
|
+
'world-of-warcraft': 'Games',
|
|
150
|
+
'elder-scrolls': 'Games',
|
|
151
|
+
'fallout': 'Games',
|
|
152
|
+
'cyberpunk': 'Games',
|
|
153
|
+
'witcher': 'Games',
|
|
154
|
+
'red-dead-redemption': 'Games',
|
|
155
|
+
'last-of-us': 'Games',
|
|
156
|
+
'god-of-war': 'Games',
|
|
157
|
+
'dark-souls': 'Games',
|
|
158
|
+
'elden-ring': 'Games',
|
|
159
|
+
'pokemon': 'Games',
|
|
160
|
+
'animal-crossing': 'Games',
|
|
161
|
+
'minecraft': 'Games',
|
|
162
|
+
// History
|
|
163
|
+
'ancient-rome': 'History',
|
|
164
|
+
'ancient-greece': 'History',
|
|
165
|
+
'ancient-egypt': 'History',
|
|
166
|
+
'renaissance': 'History',
|
|
167
|
+
'victorian-era': 'History',
|
|
168
|
+
'wild-west': 'History',
|
|
169
|
+
'world-war-2': 'History',
|
|
170
|
+
'cold-war': 'History',
|
|
171
|
+
'founding-fathers': 'History',
|
|
172
|
+
// Music
|
|
173
|
+
'classical-composers': 'Music',
|
|
174
|
+
'jazz-legends': 'Music',
|
|
175
|
+
'rock-legends': 'Music',
|
|
176
|
+
'beatles': 'Music',
|
|
177
|
+
'queen': 'Music',
|
|
178
|
+
// Science
|
|
179
|
+
'scientists': 'Science',
|
|
180
|
+
'space-exploration': 'Science',
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* Derive category from theme ID and source text.
|
|
184
|
+
* Uses CATEGORY_MAP for known themes, falls back to pattern matching.
|
|
185
|
+
*/
|
|
186
|
+
export function deriveCategory(themeId, source) {
|
|
187
|
+
if (CATEGORY_MAP[themeId]) {
|
|
188
|
+
return CATEGORY_MAP[themeId];
|
|
189
|
+
}
|
|
190
|
+
const s = source.toLowerCase();
|
|
191
|
+
if (s.includes('tv series') || s.includes('tv show') ||
|
|
192
|
+
s.includes('amc') || s.includes('hbo') ||
|
|
193
|
+
s.includes('netflix') || s.includes('bbc')) {
|
|
194
|
+
return 'TV Series';
|
|
195
|
+
}
|
|
196
|
+
if (s.includes('film') || s.includes('movie') ||
|
|
197
|
+
s.includes('cinema') || s.includes('disney') ||
|
|
198
|
+
s.includes('pixar') || s.includes('studio ghibli')) {
|
|
199
|
+
return 'Film';
|
|
200
|
+
}
|
|
201
|
+
if (s.includes('mythology') || s.includes('myth') ||
|
|
202
|
+
s.includes('legend') || s.includes('folklore')) {
|
|
203
|
+
return 'Mythology';
|
|
204
|
+
}
|
|
205
|
+
if (s.includes('novel') || s.includes('book') ||
|
|
206
|
+
s.includes(' by ') || s.includes('author') ||
|
|
207
|
+
s.includes('literary') || s.includes('classic')) {
|
|
208
|
+
return 'Literature';
|
|
209
|
+
}
|
|
210
|
+
if (s.includes('game') || s.includes('video game') ||
|
|
211
|
+
s.includes('nintendo') || s.includes('playstation') ||
|
|
212
|
+
s.includes('xbox')) {
|
|
213
|
+
return 'Games';
|
|
214
|
+
}
|
|
215
|
+
if (s.includes('history') || s.includes('historical') ||
|
|
216
|
+
s.includes('century') || s.includes('ancient') ||
|
|
217
|
+
s.includes('era')) {
|
|
218
|
+
return 'History';
|
|
219
|
+
}
|
|
220
|
+
if (s.includes('music') || s.includes('composer') ||
|
|
221
|
+
s.includes('band') || s.includes('musician')) {
|
|
222
|
+
return 'Music';
|
|
223
|
+
}
|
|
224
|
+
return 'Other';
|
|
225
|
+
}
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
227
|
+
// Theme package discovery
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
/**
|
|
230
|
+
* Discover installed @pennyfarthing/themes-* packages.
|
|
231
|
+
* Walks up from projectRoot looking for node_modules/@pennyfarthing/,
|
|
232
|
+
* then checks each themes-* directory for a valid theme pack.
|
|
233
|
+
*/
|
|
234
|
+
export function discoverThemePackages(projectRoot) {
|
|
235
|
+
const results = [];
|
|
236
|
+
const startDir = projectRoot || process.cwd();
|
|
237
|
+
// Walk up looking for node_modules/@pennyfarthing/
|
|
238
|
+
let currentDir = startDir;
|
|
239
|
+
for (let i = 0; i < 10; i++) {
|
|
240
|
+
const nmPfDir = join(currentDir, 'node_modules', '@pennyfarthing');
|
|
241
|
+
if (existsSync(nmPfDir)) {
|
|
242
|
+
try {
|
|
243
|
+
const entries = readdirSync(nmPfDir);
|
|
244
|
+
for (const entry of entries) {
|
|
245
|
+
if (!entry.startsWith('themes-'))
|
|
246
|
+
continue;
|
|
247
|
+
const pkgDir = join(nmPfDir, entry);
|
|
248
|
+
const pkgJsonPath = join(pkgDir, 'package.json');
|
|
249
|
+
if (!existsSync(pkgJsonPath))
|
|
250
|
+
continue;
|
|
251
|
+
try {
|
|
252
|
+
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
253
|
+
if (pkgJson['pennyfarthing-theme-pack'] === true) {
|
|
254
|
+
results.push({
|
|
255
|
+
packageName: pkgJson.name || `@pennyfarthing/${entry}`,
|
|
256
|
+
themesDir: join(pkgDir, 'themes'),
|
|
257
|
+
portraitsDir: join(pkgDir, 'portraits'),
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// Invalid package.json — skip
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// Can't read directory — skip
|
|
268
|
+
}
|
|
269
|
+
break; // Found node_modules, stop walking up
|
|
270
|
+
}
|
|
271
|
+
const parentDir = dirname(currentDir);
|
|
272
|
+
if (parentDir === currentDir)
|
|
273
|
+
break;
|
|
274
|
+
currentDir = parentDir;
|
|
275
|
+
}
|
|
276
|
+
// Also check monorepo packages/ directory (for development with workspace links)
|
|
277
|
+
// Walk up looking for packages/ dir containing themes-* dirs
|
|
278
|
+
currentDir = startDir;
|
|
279
|
+
for (let i = 0; i < 10; i++) {
|
|
280
|
+
const packagesDir = join(currentDir, 'packages');
|
|
281
|
+
if (existsSync(packagesDir)) {
|
|
282
|
+
try {
|
|
283
|
+
const entries = readdirSync(packagesDir);
|
|
284
|
+
for (const entry of entries) {
|
|
285
|
+
if (!entry.startsWith('themes-'))
|
|
286
|
+
continue;
|
|
287
|
+
const pkgDir = join(packagesDir, entry);
|
|
288
|
+
const pkgJsonPath = join(pkgDir, 'package.json');
|
|
289
|
+
if (!existsSync(pkgJsonPath))
|
|
290
|
+
continue;
|
|
291
|
+
// Skip if already found via node_modules
|
|
292
|
+
try {
|
|
293
|
+
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
294
|
+
if (pkgJson['pennyfarthing-theme-pack'] === true) {
|
|
295
|
+
const alreadyFound = results.some(r => r.packageName === (pkgJson.name || `@pennyfarthing/${entry}`));
|
|
296
|
+
if (!alreadyFound) {
|
|
297
|
+
results.push({
|
|
298
|
+
packageName: pkgJson.name || `@pennyfarthing/${entry}`,
|
|
299
|
+
themesDir: join(pkgDir, 'themes'),
|
|
300
|
+
portraitsDir: join(pkgDir, 'portraits'),
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
// Invalid package.json — skip
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
// Can't read directory — skip
|
|
312
|
+
}
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
const parentDir = dirname(currentDir);
|
|
316
|
+
if (parentDir === currentDir)
|
|
317
|
+
break;
|
|
318
|
+
currentDir = parentDir;
|
|
319
|
+
}
|
|
320
|
+
return results;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Discover all directories containing theme YAML files.
|
|
324
|
+
* Returns dirs in priority order (core, theme packages, project custom, user custom).
|
|
325
|
+
*/
|
|
326
|
+
export function discoverAllThemeDirs(projectRoot) {
|
|
327
|
+
const dirs = [];
|
|
328
|
+
const root = projectRoot || process.cwd();
|
|
329
|
+
// 1. Core themes from pennyfarthing-dist
|
|
330
|
+
const distPath = resolvePennyfarthingDist();
|
|
331
|
+
if (distPath) {
|
|
332
|
+
const paths = getPortraitPaths(distPath);
|
|
333
|
+
const coreThemesDir = join(paths.themesDir, 'themes');
|
|
334
|
+
if (existsSync(coreThemesDir)) {
|
|
335
|
+
dirs.push(coreThemesDir);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
// 2. Theme packages (e.g., @pennyfarthing/themes-realistic)
|
|
339
|
+
const packages = discoverThemePackages(root);
|
|
340
|
+
for (const pkg of packages) {
|
|
341
|
+
if (existsSync(pkg.themesDir)) {
|
|
342
|
+
dirs.push(pkg.themesDir);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// 3. Project-level custom themes
|
|
346
|
+
const projectCustom = join(root, '.claude', 'pennyfarthing', 'themes');
|
|
347
|
+
if (existsSync(projectCustom)) {
|
|
348
|
+
dirs.push(projectCustom);
|
|
349
|
+
}
|
|
350
|
+
// 4. User-level custom themes
|
|
351
|
+
const userCustom = join(homedir(), '.claude', 'pennyfarthing', 'themes');
|
|
352
|
+
if (existsSync(userCustom)) {
|
|
353
|
+
dirs.push(userCustom);
|
|
354
|
+
}
|
|
355
|
+
return dirs;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Resolve the file path for a specific theme across all sources.
|
|
359
|
+
* Returns the first match found in priority order, or null.
|
|
360
|
+
*/
|
|
361
|
+
export function resolveThemePath(themeId, projectRoot) {
|
|
362
|
+
const dirs = discoverAllThemeDirs(projectRoot);
|
|
363
|
+
for (const dir of dirs) {
|
|
364
|
+
const themePath = join(dir, `${themeId}.yaml`);
|
|
365
|
+
if (existsSync(themePath)) {
|
|
366
|
+
return themePath;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
// ---------------------------------------------------------------------------
|
|
372
|
+
// Theme metadata loading
|
|
373
|
+
// ---------------------------------------------------------------------------
|
|
374
|
+
/**
|
|
375
|
+
* Load metadata for all discoverable themes.
|
|
376
|
+
* Deduplicates by theme ID (first source wins).
|
|
377
|
+
*/
|
|
378
|
+
export function loadAllThemeMetadata(projectRoot) {
|
|
379
|
+
const dirs = discoverAllThemeDirs(projectRoot);
|
|
380
|
+
const seenIds = new Set();
|
|
381
|
+
const metadata = [];
|
|
382
|
+
for (const dir of dirs) {
|
|
383
|
+
let files;
|
|
384
|
+
try {
|
|
385
|
+
files = readdirSync(dir).filter(f => f.endsWith('.yaml')).sort();
|
|
386
|
+
}
|
|
387
|
+
catch {
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
for (const file of files) {
|
|
391
|
+
const themeId = basename(file, '.yaml');
|
|
392
|
+
if (seenIds.has(themeId))
|
|
393
|
+
continue;
|
|
394
|
+
seenIds.add(themeId);
|
|
395
|
+
try {
|
|
396
|
+
const content = readFileSync(join(dir, file), 'utf-8');
|
|
397
|
+
const parsed = parseYaml(content);
|
|
398
|
+
if (!parsed?.theme)
|
|
399
|
+
continue;
|
|
400
|
+
const agentCount = parsed.agents ? Object.keys(parsed.agents).length : 0;
|
|
401
|
+
metadata.push({
|
|
402
|
+
id: themeId,
|
|
403
|
+
name: parsed.theme.name || themeId,
|
|
404
|
+
description: parsed.theme.description || '',
|
|
405
|
+
source: parsed.theme.source || '',
|
|
406
|
+
tier: parsed.theme.tier || 'U',
|
|
407
|
+
category: deriveCategory(themeId, parsed.theme.source || ''),
|
|
408
|
+
agentCount,
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
// Skip unparseable files
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return metadata;
|
|
417
|
+
}
|
|
418
|
+
// ---------------------------------------------------------------------------
|
|
419
|
+
// Existing API (kept stable)
|
|
420
|
+
// ---------------------------------------------------------------------------
|
|
421
|
+
/**
|
|
422
|
+
* Load a theme configuration by name.
|
|
423
|
+
* Searches all theme sources in priority order.
|
|
424
|
+
*/
|
|
425
|
+
export function loadTheme(themeName) {
|
|
426
|
+
const themePath = resolveThemePath(themeName);
|
|
427
|
+
if (!themePath) {
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
const content = readFileSync(themePath, 'utf-8');
|
|
432
|
+
const raw = parseYaml(content);
|
|
433
|
+
const agents = {};
|
|
434
|
+
for (const [agentKey, agentData] of Object.entries(raw.agents || {})) {
|
|
435
|
+
agents[agentKey] = {
|
|
436
|
+
character: agentData.character || '',
|
|
437
|
+
style: agentData.style || '',
|
|
438
|
+
role: agentData.role || '',
|
|
439
|
+
trait: agentData.trait || '',
|
|
440
|
+
catchphrases: agentData.catchphrases || [],
|
|
441
|
+
helper: agentData.helper?.name,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
name: themeName,
|
|
446
|
+
description: raw.theme?.description || '',
|
|
447
|
+
agents,
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
catch {
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* List all available theme IDs across all sources.
|
|
456
|
+
* Deduplicates — first source wins.
|
|
457
|
+
*/
|
|
458
|
+
export function listThemes(projectRoot) {
|
|
459
|
+
const dirs = discoverAllThemeDirs(projectRoot);
|
|
460
|
+
const seenIds = new Set();
|
|
461
|
+
const themeIds = [];
|
|
462
|
+
for (const dir of dirs) {
|
|
463
|
+
try {
|
|
464
|
+
const files = readdirSync(dir);
|
|
465
|
+
for (const f of files) {
|
|
466
|
+
if (!f.endsWith('.yaml'))
|
|
467
|
+
continue;
|
|
468
|
+
const id = basename(f, '.yaml');
|
|
469
|
+
if (!seenIds.has(id)) {
|
|
470
|
+
seenIds.add(id);
|
|
471
|
+
themeIds.push(id);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
catch {
|
|
476
|
+
// Skip unreadable dirs
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return themeIds;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Get agent persona from a theme.
|
|
483
|
+
*/
|
|
484
|
+
export function getAgentPersona(themeName, agentName) {
|
|
485
|
+
const theme = loadTheme(themeName);
|
|
486
|
+
if (!theme) {
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
return theme.agents[agentName] || null;
|
|
490
|
+
}
|
|
491
|
+
//# sourceMappingURL=theme-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-loader.js","sourceRoot":"","sources":["../src/theme-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-loader.test.d.ts","sourceRoot":"","sources":["../src/theme-loader.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Schema Consolidation Tests - MSSCI-12478
|
|
3
|
+
*
|
|
4
|
+
* Tests for consolidating quote field into catchphrases array.
|
|
5
|
+
* RED STATE: These tests should FAIL until implementation is complete.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it } from 'node:test';
|
|
8
|
+
import assert from 'node:assert';
|
|
9
|
+
import { loadTheme } from './theme-loader.js';
|
|
10
|
+
describe('MSSCI-12478: Theme Schema Consolidation', () => {
|
|
11
|
+
describe('AC3: quote field removed from schema', () => {
|
|
12
|
+
it('ThemeAgent interface should have catchphrases array, not quote string', () => {
|
|
13
|
+
// Load any theme and check the agent structure
|
|
14
|
+
const theme = loadTheme('the-expanse');
|
|
15
|
+
assert.ok(theme !== null, 'Theme should load');
|
|
16
|
+
const agent = theme.agents['sm'];
|
|
17
|
+
assert.ok(agent !== undefined, 'SM agent should exist');
|
|
18
|
+
// Should have catchphrases array
|
|
19
|
+
assert.ok('catchphrases' in agent, 'Agent should have catchphrases property');
|
|
20
|
+
assert.ok(Array.isArray(agent.catchphrases), 'catchphrases should be an array');
|
|
21
|
+
// Should NOT have quote field (removed from schema)
|
|
22
|
+
assert.ok(!('quote' in agent), 'Agent should NOT have quote property after migration');
|
|
23
|
+
});
|
|
24
|
+
it('catchphrases array should contain at least one entry', () => {
|
|
25
|
+
const theme = loadTheme('the-expanse');
|
|
26
|
+
assert.ok(theme !== null, 'Theme should load');
|
|
27
|
+
const agent = theme.agents['tea'];
|
|
28
|
+
assert.ok(agent.catchphrases !== undefined, 'catchphrases should be defined');
|
|
29
|
+
assert.ok(agent.catchphrases.length > 0, 'catchphrases should have at least one entry');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('AC1: Migration script merges quote into catchphrases', () => {
|
|
33
|
+
it('original quote should be present in catchphrases array', () => {
|
|
34
|
+
// The Investigator's quote was "Doors and corners, kid. That's where they get you."
|
|
35
|
+
// After migration, this should be in the catchphrases array
|
|
36
|
+
const theme = loadTheme('the-expanse');
|
|
37
|
+
assert.ok(theme !== null, 'Theme should load');
|
|
38
|
+
const agent = theme.agents['orchestrator'];
|
|
39
|
+
assert.ok(agent.catchphrases.includes("Doors and corners, kid. That's where they get you."), 'Original quote should be in catchphrases array');
|
|
40
|
+
});
|
|
41
|
+
it('catchphrases should not have duplicates after migration', () => {
|
|
42
|
+
const theme = loadTheme('the-expanse');
|
|
43
|
+
assert.ok(theme !== null, 'Theme should load');
|
|
44
|
+
const agent = theme.agents['sm'];
|
|
45
|
+
// Check for duplicates
|
|
46
|
+
const uniqueCatchphrases = [...new Set(agent.catchphrases)];
|
|
47
|
+
assert.strictEqual(agent.catchphrases.length, uniqueCatchphrases.length, 'catchphrases should have no duplicates');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('AC4: Theme validation updated', () => {
|
|
51
|
+
it('should parse catchphrases array from YAML', () => {
|
|
52
|
+
const theme = loadTheme('star-trek-tng');
|
|
53
|
+
assert.ok(theme !== null, 'Theme should load');
|
|
54
|
+
// Every agent should have catchphrases parsed
|
|
55
|
+
for (const [agentName, agent] of Object.entries(theme.agents)) {
|
|
56
|
+
assert.ok(agent.catchphrases !== undefined, `Agent ${agentName} should have catchphrases`);
|
|
57
|
+
assert.ok(Array.isArray(agent.catchphrases), `Agent ${agentName} catchphrases should be array`);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=theme-loader.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-loader.test.js","sourceRoot":"","sources":["../src/theme-loader.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pennyfarthing/shared",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.3.0",
|
|
4
4
|
"description": "Shared utilities for Pennyfarthing including portrait path resolution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./browser": {
|
|
14
|
+
"types": "./dist/browser.d.ts",
|
|
15
|
+
"default": "./dist/browser.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
8
18
|
"files": [
|
|
9
19
|
"dist/"
|
|
10
20
|
],
|
|
@@ -34,5 +44,8 @@
|
|
|
34
44
|
"devDependencies": {
|
|
35
45
|
"@types/node": "^20.10.0",
|
|
36
46
|
"typescript": "^5.3.3"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"yaml": "^2.8.2"
|
|
37
50
|
}
|
|
38
51
|
}
|