@pennyfarthing/shared 7.9.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.
@@ -8,7 +8,7 @@
8
8
  * 4. Scoped npm (node_modules/@pennyfarthing/core/pennyfarthing-dist/)
9
9
  * 5. Legacy npm (node_modules/pennyfarthing/pennyfarthing-dist/)
10
10
  */
11
- import { existsSync, readdirSync } from 'node:fs';
11
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
12
12
  import { join, dirname, resolve } from 'node:path';
13
13
  import { fileURLToPath } from 'node:url';
14
14
  // Get the directory where this module is located
@@ -64,25 +64,13 @@ export function resolvePennyfarthingDist() {
64
64
  return null;
65
65
  }
66
66
  /**
67
- * Resolve the full path to a portrait image
68
- * @param theme - Theme name (e.g., 'shakespeare', 'norse-mythology')
69
- * @param agent - Agent name (e.g., 'sm', 'tea', 'dev')
70
- * @returns Full path to portrait file, or null if not found
67
+ * Find portrait in a specific theme directory.
68
+ * Shared logic for both core and theme package portrait resolution.
71
69
  */
72
- export function resolvePortraitPath(theme, agent) {
73
- const distPath = resolvePennyfarthingDist();
74
- if (!distPath) {
75
- return null;
76
- }
77
- const paths = getPortraitPaths(distPath);
78
- const portraitsThemeDir = join(paths.portraitsDir, theme);
70
+ function findPortraitInDir(portraitsThemeDir, agent) {
79
71
  if (!existsSync(portraitsThemeDir)) {
80
72
  return null;
81
73
  }
82
- // Look for portrait file matching the agent
83
- // Portraits are in size subdirectories: large/, medium/, small/, original/
84
- // Portraits follow pattern: {shortName}-{ocean}.png
85
- // Agent names in tests may be short names (sm, tea, dev) or need mapping
86
74
  try {
87
75
  // Check size subdirectories in preference order
88
76
  const sizeDirectories = ['large', 'medium', 'small', 'original'];
@@ -102,9 +90,6 @@ export function resolvePortraitPath(theme, agent) {
102
90
  searchDir = portraitsThemeDir;
103
91
  }
104
92
  // Map agent names to portrait file prefixes based on theme conventions
105
- // For most themes, portrait names use character short names
106
- // We need to find a file that contains the agent name or its mapping
107
- // Note: This includes characters from multiple themes (shakespeare, norse, a-team)
108
93
  const agentMappings = {
109
94
  'sm': ['prospero', 'baldur', 'face', 'faceman', 'sm'],
110
95
  'tea': ['hamlet', 'tyr', 'murdock', 'tea'],
@@ -132,6 +117,99 @@ export function resolvePortraitPath(theme, agent) {
132
117
  }
133
118
  return null;
134
119
  }
120
+ /**
121
+ * Discover theme package portrait directories.
122
+ * Inlined here to avoid circular dependency with theme-loader.ts.
123
+ */
124
+ function discoverThemePackagePortraitDirs() {
125
+ const results = [];
126
+ let currentDir = process.cwd();
127
+ // Check node_modules/@pennyfarthing/themes-*
128
+ for (let i = 0; i < 10; i++) {
129
+ const nmPfDir = join(currentDir, 'node_modules', '@pennyfarthing');
130
+ if (existsSync(nmPfDir)) {
131
+ try {
132
+ for (const entry of readdirSync(nmPfDir)) {
133
+ if (!entry.startsWith('themes-'))
134
+ continue;
135
+ const pkgJsonPath = join(nmPfDir, entry, 'package.json');
136
+ if (!existsSync(pkgJsonPath))
137
+ continue;
138
+ try {
139
+ const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
140
+ if (pkgJson['pennyfarthing-theme-pack'] === true) {
141
+ results.push({ portraitsDir: join(nmPfDir, entry, 'portraits') });
142
+ }
143
+ }
144
+ catch { /* skip */ }
145
+ }
146
+ }
147
+ catch { /* skip */ }
148
+ break;
149
+ }
150
+ const parentDir = dirname(currentDir);
151
+ if (parentDir === currentDir)
152
+ break;
153
+ currentDir = parentDir;
154
+ }
155
+ // Check monorepo packages/themes-*
156
+ currentDir = process.cwd();
157
+ for (let i = 0; i < 10; i++) {
158
+ const packagesDir = join(currentDir, 'packages');
159
+ if (existsSync(packagesDir)) {
160
+ try {
161
+ for (const entry of readdirSync(packagesDir)) {
162
+ if (!entry.startsWith('themes-'))
163
+ continue;
164
+ const pkgJsonPath = join(packagesDir, entry, 'package.json');
165
+ if (!existsSync(pkgJsonPath))
166
+ continue;
167
+ try {
168
+ const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
169
+ if (pkgJson['pennyfarthing-theme-pack'] === true) {
170
+ const portraitsDir = join(packagesDir, entry, 'portraits');
171
+ if (!results.some(r => r.portraitsDir === portraitsDir)) {
172
+ results.push({ portraitsDir });
173
+ }
174
+ }
175
+ }
176
+ catch { /* skip */ }
177
+ }
178
+ }
179
+ catch { /* skip */ }
180
+ break;
181
+ }
182
+ const parentDir = dirname(currentDir);
183
+ if (parentDir === currentDir)
184
+ break;
185
+ currentDir = parentDir;
186
+ }
187
+ return results;
188
+ }
189
+ /**
190
+ * Resolve the full path to a portrait image
191
+ * @param theme - Theme name (e.g., 'shakespeare', 'norse-mythology')
192
+ * @param agent - Agent name (e.g., 'sm', 'tea', 'dev')
193
+ * @returns Full path to portrait file, or null if not found
194
+ */
195
+ export function resolvePortraitPath(theme, agent) {
196
+ // 1. Check core portraits
197
+ const distPath = resolvePennyfarthingDist();
198
+ if (distPath) {
199
+ const paths = getPortraitPaths(distPath);
200
+ const coreResult = findPortraitInDir(join(paths.portraitsDir, theme), agent);
201
+ if (coreResult)
202
+ return coreResult;
203
+ }
204
+ // 2. Check theme package portraits
205
+ const themePackages = discoverThemePackagePortraitDirs();
206
+ for (const pkg of themePackages) {
207
+ const pkgResult = findPortraitInDir(join(pkg.portraitsDir, theme), agent);
208
+ if (pkgResult)
209
+ return pkgResult;
210
+ }
211
+ return null;
212
+ }
135
213
  /**
136
214
  * Get all portrait-related paths for a resolved dist directory
137
215
  */
@@ -1 +1 @@
1
- {"version":3,"file":"portrait-resolver.js","sourceRoot":"","sources":["../src/portrait-resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"portrait-resolver.js","sourceRoot":"","sources":["../src/portrait-resolver.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,14 @@
1
1
  /**
2
- * Theme Loader - Load and parse Pennyfarthing theme configurations
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/
3
12
  */
4
13
  export interface ThemeAgent {
5
14
  character: string;
@@ -14,22 +23,59 @@ export interface Theme {
14
23
  description: string;
15
24
  agents: Record<string, ThemeAgent>;
16
25
  }
26
+ export interface ThemePackageInfo {
27
+ packageName: string;
28
+ themesDir: string;
29
+ portraitsDir: string;
30
+ }
31
+ export interface ThemeMetadata {
32
+ id: string;
33
+ name: string;
34
+ description: string;
35
+ source: string;
36
+ tier: 'S' | 'A' | 'B' | 'U';
37
+ category: string;
38
+ agentCount: number;
39
+ }
40
+ export declare const CATEGORY_MAP: Record<string, string>;
41
+ /**
42
+ * Derive category from theme ID and source text.
43
+ * Uses CATEGORY_MAP for known themes, falls back to pattern matching.
44
+ */
45
+ export declare function deriveCategory(themeId: string, source: string): string;
46
+ /**
47
+ * Discover installed @pennyfarthing/themes-* packages.
48
+ * Walks up from projectRoot looking for node_modules/@pennyfarthing/,
49
+ * then checks each themes-* directory for a valid theme pack.
50
+ */
51
+ export declare function discoverThemePackages(projectRoot?: string): ThemePackageInfo[];
52
+ /**
53
+ * Discover all directories containing theme YAML files.
54
+ * Returns dirs in priority order (core, theme packages, project custom, user custom).
55
+ */
56
+ export declare function discoverAllThemeDirs(projectRoot?: string): string[];
57
+ /**
58
+ * Resolve the file path for a specific theme across all sources.
59
+ * Returns the first match found in priority order, or null.
60
+ */
61
+ export declare function resolveThemePath(themeId: string, projectRoot?: string): string | null;
62
+ /**
63
+ * Load metadata for all discoverable themes.
64
+ * Deduplicates by theme ID (first source wins).
65
+ */
66
+ export declare function loadAllThemeMetadata(projectRoot?: string): ThemeMetadata[];
17
67
  /**
18
- * Load a theme configuration by name
19
- * @param themeName - Name of the theme (e.g., 'shakespeare', 'norse-mythology')
20
- * @returns Parsed theme configuration or null if not found
68
+ * Load a theme configuration by name.
69
+ * Searches all theme sources in priority order.
21
70
  */
22
71
  export declare function loadTheme(themeName: string): Theme | null;
23
72
  /**
24
- * List all available themes
25
- * @returns Array of theme names
73
+ * List all available theme IDs across all sources.
74
+ * Deduplicates first source wins.
26
75
  */
27
- export declare function listThemes(): string[];
76
+ export declare function listThemes(projectRoot?: string): string[];
28
77
  /**
29
- * Get agent persona from a theme
30
- * @param themeName - Theme name
31
- * @param agentName - Agent name (e.g., 'sm', 'tea', 'dev')
32
- * @returns Agent persona or null if not found
78
+ * Get agent persona from a theme.
33
79
  */
34
80
  export declare function getAgentPersona(themeName: string, agentName: string): ThemeAgent | null;
35
81
  //# sourceMappingURL=theme-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"theme-loader.d.ts","sourceRoot":"","sources":["../src/theme-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC;AAoBD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAqCzD;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,EAAE,CAqBrC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAOvF"}
1
+ {"version":3,"file":"theme-loader.d.ts","sourceRoot":"","sources":["../src/theme-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAYH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC;AAMD,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AA8BD,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAgK/C,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CA0CtE;AAMD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAoF9E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAmCnE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASrF;AAMD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE,CAyC1E;AAMD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CA8BzD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAsBzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAMvF"}