@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.
- 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 +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.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 +147 -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 +193 -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 +35 -0
- package/dist/theme-loader.d.ts.map +1 -0
- package/dist/theme-loader.js +170 -0
- package/dist/theme-loader.js.map +1 -0
- package/dist/theme-loader.test.d.ts +2 -0
- package/dist/theme-loader.test.d.ts.map +1 -0
- package/dist/theme-loader.test.js +72 -0
- package/dist/theme-loader.test.js.map +1 -0
- 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 @@
|
|
|
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
|
+
}
|