@pennyfarthing/shared 7.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/generate-skill-docs.d.ts +35 -0
  2. package/dist/generate-skill-docs.d.ts.map +1 -0
  3. package/dist/generate-skill-docs.js +442 -0
  4. package/dist/generate-skill-docs.js.map +1 -0
  5. package/dist/generate-skill-docs.test.d.ts +13 -0
  6. package/dist/generate-skill-docs.test.d.ts.map +1 -0
  7. package/dist/generate-skill-docs.test.js +519 -0
  8. package/dist/generate-skill-docs.test.js.map +1 -0
  9. package/dist/index.d.ts +10 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +10 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/portrait-resolver.d.ts +32 -0
  14. package/dist/portrait-resolver.d.ts.map +1 -0
  15. package/dist/portrait-resolver.js +147 -0
  16. package/dist/portrait-resolver.js.map +1 -0
  17. package/dist/portrait-resolver.test.d.ts +2 -0
  18. package/dist/portrait-resolver.test.d.ts.map +1 -0
  19. package/dist/portrait-resolver.test.js +156 -0
  20. package/dist/portrait-resolver.test.js.map +1 -0
  21. package/dist/skill-search.d.ts +36 -0
  22. package/dist/skill-search.d.ts.map +1 -0
  23. package/dist/skill-search.js +300 -0
  24. package/dist/skill-search.js.map +1 -0
  25. package/dist/skill-search.sh +41 -0
  26. package/dist/skill-search.test.d.ts +16 -0
  27. package/dist/skill-search.test.d.ts.map +1 -0
  28. package/dist/skill-search.test.js +193 -0
  29. package/dist/skill-search.test.js.map +1 -0
  30. package/dist/skill-suggest.d.ts +76 -0
  31. package/dist/skill-suggest.d.ts.map +1 -0
  32. package/dist/skill-suggest.js +256 -0
  33. package/dist/skill-suggest.js.map +1 -0
  34. package/dist/skill-suggest.test.d.ts +12 -0
  35. package/dist/skill-suggest.test.d.ts.map +1 -0
  36. package/dist/skill-suggest.test.js +257 -0
  37. package/dist/skill-suggest.test.js.map +1 -0
  38. package/dist/theme-loader.d.ts +35 -0
  39. package/dist/theme-loader.d.ts.map +1 -0
  40. package/dist/theme-loader.js +170 -0
  41. package/dist/theme-loader.js.map +1 -0
  42. package/dist/theme-loader.test.d.ts +2 -0
  43. package/dist/theme-loader.test.d.ts.map +1 -0
  44. package/dist/theme-loader.test.js +72 -0
  45. package/dist/theme-loader.test.js.map +1 -0
  46. package/package.json +38 -0
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Theme Loader - Load and parse Pennyfarthing theme configurations
3
+ */
4
+ export interface ThemeAgent {
5
+ character: string;
6
+ style: string;
7
+ role: string;
8
+ trait: string;
9
+ quote: string;
10
+ helper?: string;
11
+ }
12
+ export interface Theme {
13
+ name: string;
14
+ description: string;
15
+ agents: Record<string, ThemeAgent>;
16
+ }
17
+ /**
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
21
+ */
22
+ export declare function loadTheme(themeName: string): Theme | null;
23
+ /**
24
+ * List all available themes
25
+ * @returns Array of theme names
26
+ */
27
+ export declare function listThemes(): string[];
28
+ /**
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
33
+ */
34
+ export declare function getAgentPersona(themeName: string, agentName: string): ThemeAgent | null;
35
+ //# sourceMappingURL=theme-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-loader.d.ts","sourceRoot":"","sources":["../src/theme-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,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;AAoGD;;;;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"}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Theme Loader - Load and parse Pennyfarthing theme configurations
3
+ */
4
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
5
+ import { join, basename } from 'node:path';
6
+ import { resolvePennyfarthingDist, getPortraitPaths } from './portrait-resolver.js';
7
+ /**
8
+ * Simple YAML parser for theme files
9
+ * Only handles the specific YAML structure we need
10
+ */
11
+ function parseYaml(content) {
12
+ const result = { theme: {}, agents: {} };
13
+ const lines = content.split('\n');
14
+ let currentSection = null;
15
+ let currentAgent = null;
16
+ let currentSubsection = null;
17
+ for (const line of lines) {
18
+ const trimmed = line.trimEnd();
19
+ // Skip empty lines and comments
20
+ if (!trimmed || trimmed.startsWith('#'))
21
+ continue;
22
+ // Count leading spaces to determine indent level
23
+ const indent = line.length - line.trimStart().length;
24
+ const key = trimmed.split(':')[0].trim();
25
+ const value = trimmed.includes(':') ? trimmed.substring(trimmed.indexOf(':') + 1).trim() : '';
26
+ if (indent === 0) {
27
+ if (key === 'theme') {
28
+ currentSection = 'theme';
29
+ currentAgent = null;
30
+ }
31
+ else if (key === 'agents') {
32
+ currentSection = 'agents';
33
+ currentAgent = null;
34
+ }
35
+ }
36
+ else if (indent === 2 && currentSection === 'theme') {
37
+ if (key === 'name') {
38
+ result.theme.name = value.replace(/^["']|["']$/g, '');
39
+ }
40
+ else if (key === 'description') {
41
+ result.theme.description = value.replace(/^["']|["']$/g, '');
42
+ }
43
+ }
44
+ else if (indent === 2 && currentSection === 'agents') {
45
+ currentAgent = key;
46
+ if (!result.agents[currentAgent]) {
47
+ result.agents[currentAgent] = {};
48
+ }
49
+ currentSubsection = null;
50
+ }
51
+ else if (indent === 4 && currentSection === 'agents' && currentAgent) {
52
+ const cleanValue = value.replace(/^["']|["']$/g, '');
53
+ if (key === 'character') {
54
+ result.agents[currentAgent].character = cleanValue;
55
+ }
56
+ else if (key === 'style') {
57
+ result.agents[currentAgent].style = cleanValue;
58
+ }
59
+ else if (key === 'role') {
60
+ result.agents[currentAgent].role = cleanValue;
61
+ }
62
+ else if (key === 'trait') {
63
+ result.agents[currentAgent].trait = cleanValue;
64
+ }
65
+ else if (key === 'quote') {
66
+ result.agents[currentAgent].quote = cleanValue;
67
+ }
68
+ else if (key === 'shortName') {
69
+ result.agents[currentAgent].shortName = cleanValue;
70
+ }
71
+ else if (key === 'helper') {
72
+ currentSubsection = 'helper';
73
+ result.agents[currentAgent].helper = {};
74
+ }
75
+ }
76
+ else if (indent === 6 && currentSubsection === 'helper' && currentAgent) {
77
+ const cleanValue = value.replace(/^["']|["']$/g, '');
78
+ if (key === 'name') {
79
+ if (!result.agents[currentAgent].helper) {
80
+ result.agents[currentAgent].helper = {};
81
+ }
82
+ result.agents[currentAgent].helper.name = cleanValue;
83
+ }
84
+ else if (key === 'style') {
85
+ if (!result.agents[currentAgent].helper) {
86
+ result.agents[currentAgent].helper = {};
87
+ }
88
+ result.agents[currentAgent].helper.style = cleanValue;
89
+ }
90
+ }
91
+ }
92
+ return result;
93
+ }
94
+ /**
95
+ * Load a theme configuration by name
96
+ * @param themeName - Name of the theme (e.g., 'shakespeare', 'norse-mythology')
97
+ * @returns Parsed theme configuration or null if not found
98
+ */
99
+ export function loadTheme(themeName) {
100
+ const distPath = resolvePennyfarthingDist();
101
+ if (!distPath) {
102
+ return null;
103
+ }
104
+ const paths = getPortraitPaths(distPath);
105
+ const themePath = join(paths.themesDir, 'themes', `${themeName}.yaml`);
106
+ if (!existsSync(themePath)) {
107
+ return null;
108
+ }
109
+ try {
110
+ const content = readFileSync(themePath, 'utf-8');
111
+ const raw = parseYaml(content);
112
+ const agents = {};
113
+ for (const [agentKey, agentData] of Object.entries(raw.agents || {})) {
114
+ agents[agentKey] = {
115
+ character: agentData.character || '',
116
+ style: agentData.style || '',
117
+ role: agentData.role || '',
118
+ trait: agentData.trait || '',
119
+ quote: agentData.quote || '',
120
+ helper: agentData.helper?.name,
121
+ };
122
+ }
123
+ return {
124
+ name: themeName,
125
+ description: raw.theme?.description || '',
126
+ agents,
127
+ };
128
+ }
129
+ catch {
130
+ return null;
131
+ }
132
+ }
133
+ /**
134
+ * List all available themes
135
+ * @returns Array of theme names
136
+ */
137
+ export function listThemes() {
138
+ const distPath = resolvePennyfarthingDist();
139
+ if (!distPath) {
140
+ return [];
141
+ }
142
+ const paths = getPortraitPaths(distPath);
143
+ const themesDir = join(paths.themesDir, 'themes');
144
+ if (!existsSync(themesDir)) {
145
+ return [];
146
+ }
147
+ try {
148
+ const files = readdirSync(themesDir);
149
+ return files
150
+ .filter(f => f.endsWith('.yaml'))
151
+ .map(f => basename(f, '.yaml'));
152
+ }
153
+ catch {
154
+ return [];
155
+ }
156
+ }
157
+ /**
158
+ * Get agent persona from a theme
159
+ * @param themeName - Theme name
160
+ * @param agentName - Agent name (e.g., 'sm', 'tea', 'dev')
161
+ * @returns Agent persona or null if not found
162
+ */
163
+ export function getAgentPersona(themeName, agentName) {
164
+ const theme = loadTheme(themeName);
165
+ if (!theme) {
166
+ return null;
167
+ }
168
+ return theme.agents[agentName] || null;
169
+ }
170
+ //# 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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=theme-loader.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-loader.test.d.ts","sourceRoot":"","sources":["../src/theme-loader.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,72 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { loadTheme, listThemes, getAgentPersona, } from './theme-loader.js';
4
+ describe('theme-loader', () => {
5
+ describe('loadTheme', () => {
6
+ it('should load a valid theme by name', () => {
7
+ const theme = loadTheme('shakespeare');
8
+ assert.ok(theme !== null, 'Should find theme');
9
+ assert.strictEqual(theme.name, 'shakespeare');
10
+ assert.ok('agents' in theme, 'Should have agents');
11
+ });
12
+ it('should return null for invalid theme name', () => {
13
+ const theme = loadTheme('nonexistent-theme-xyz');
14
+ assert.strictEqual(theme, null);
15
+ });
16
+ it('should include all required agent personas', () => {
17
+ const theme = loadTheme('shakespeare');
18
+ assert.ok(theme !== null);
19
+ const requiredAgents = ['sm', 'tea', 'dev', 'reviewer'];
20
+ for (const agent of requiredAgents) {
21
+ assert.ok(agent in theme.agents, `Should have ${agent} persona`);
22
+ }
23
+ });
24
+ it('should parse agent properties correctly', () => {
25
+ const theme = loadTheme('shakespeare');
26
+ assert.ok(theme !== null);
27
+ const smAgent = theme.agents['sm'];
28
+ assert.ok('character' in smAgent, 'Agent should have character');
29
+ assert.ok('style' in smAgent, 'Agent should have style');
30
+ assert.ok('role' in smAgent, 'Agent should have role');
31
+ assert.ok('quote' in smAgent, 'Agent should have quote');
32
+ });
33
+ });
34
+ describe('listThemes', () => {
35
+ it('should return array of theme names', () => {
36
+ const themes = listThemes();
37
+ assert.ok(Array.isArray(themes), 'Should return array');
38
+ assert.ok(themes.length > 0, 'Should have at least one theme');
39
+ });
40
+ it('should include known themes', () => {
41
+ const themes = listThemes();
42
+ // These themes should exist based on project structure
43
+ const knownThemes = ['shakespeare', 'norse-mythology', 'star-trek'];
44
+ for (const known of knownThemes) {
45
+ assert.ok(themes.some(t => t.includes(known.split('-')[0])), `Should include theme matching ${known}`);
46
+ }
47
+ });
48
+ });
49
+ describe('getAgentPersona', () => {
50
+ it('should return agent persona for valid theme and agent', () => {
51
+ const persona = getAgentPersona('shakespeare', 'sm');
52
+ assert.ok(persona !== null, 'Should find persona');
53
+ assert.ok('character' in persona, 'Should have character');
54
+ });
55
+ it('should return null for invalid theme', () => {
56
+ const persona = getAgentPersona('nonexistent', 'sm');
57
+ assert.strictEqual(persona, null);
58
+ });
59
+ it('should return null for invalid agent', () => {
60
+ const persona = getAgentPersona('shakespeare', 'nonexistent-agent');
61
+ assert.strictEqual(persona, null);
62
+ });
63
+ it('should return correct character for known persona', () => {
64
+ // We know shakespeare theme has specific characters
65
+ const persona = getAgentPersona('shakespeare', 'sm');
66
+ assert.ok(persona !== null);
67
+ assert.ok(typeof persona.character === 'string');
68
+ assert.ok(persona.character.length > 0);
69
+ });
70
+ });
71
+ });
72
+ //# 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 ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@pennyfarthing/shared",
3
+ "version": "7.0.2",
4
+ "description": "Shared utilities for Pennyfarthing including portrait path resolution",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist/"
10
+ ],
11
+ "keywords": [
12
+ "pennyfarthing",
13
+ "shared",
14
+ "portrait-resolver"
15
+ ],
16
+ "license": "UNLICENSED",
17
+ "author": "1898andCo",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/1898andCo/pennyfarthing.git",
21
+ "directory": "packages/shared"
22
+ },
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "engines": {
27
+ "node": ">=18.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^20.10.0",
31
+ "typescript": "^5.3.3"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc && cp src/*.sh dist/ 2>/dev/null || true",
35
+ "test": "node --test dist/*.test.js",
36
+ "clean": "rm -rf dist/"
37
+ }
38
+ }