@pennyfarthing/shared 7.5.0 → 7.9.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/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 +37 -0
- package/dist/marker/constants.d.ts.map +1 -0
- package/dist/marker/constants.js +43 -0
- package/dist/marker/constants.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 +417 -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 +67 -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 +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 +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 +35 -0
- package/dist/theme-loader.d.ts.map +1 -0
- package/dist/theme-loader.js +84 -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 +4 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip functions for the Reflector marker system.
|
|
3
|
+
*
|
|
4
|
+
* @see docs/adr/0011-reflector-marker-consolidation.md
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Strip fenced code blocks from text.
|
|
8
|
+
*
|
|
9
|
+
* Used before marker detection to ensure markers inside code blocks
|
|
10
|
+
* are not processed as actual markers.
|
|
11
|
+
*
|
|
12
|
+
* @param text - Text potentially containing fenced code blocks
|
|
13
|
+
* @returns Text with code blocks removed
|
|
14
|
+
*/
|
|
15
|
+
export declare function stripCodeBlocks(text: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Strip CYCLIST markers from text for display.
|
|
18
|
+
*
|
|
19
|
+
* Removes all CYCLIST markers while preserving surrounding text.
|
|
20
|
+
* Useful for cleaning agent output before displaying to users.
|
|
21
|
+
*
|
|
22
|
+
* @param text - Text containing markers
|
|
23
|
+
* @returns Text with markers removed
|
|
24
|
+
*/
|
|
25
|
+
export declare function stripMarkers(text: string): string;
|
|
26
|
+
//# sourceMappingURL=strip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strip.d.ts","sourceRoot":"","sources":["../../src/marker/strip.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOjD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip functions for the Reflector marker system.
|
|
3
|
+
*
|
|
4
|
+
* @see docs/adr/0011-reflector-marker-consolidation.md
|
|
5
|
+
*/
|
|
6
|
+
import { MARKER_PATTERN } from './constants.js';
|
|
7
|
+
/**
|
|
8
|
+
* Strip fenced code blocks from text.
|
|
9
|
+
*
|
|
10
|
+
* Used before marker detection to ensure markers inside code blocks
|
|
11
|
+
* are not processed as actual markers.
|
|
12
|
+
*
|
|
13
|
+
* @param text - Text potentially containing fenced code blocks
|
|
14
|
+
* @returns Text with code blocks removed
|
|
15
|
+
*/
|
|
16
|
+
export function stripCodeBlocks(text) {
|
|
17
|
+
if (!text) {
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
return text.replace(/```[\s\S]*?```/g, '');
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Strip CYCLIST markers from text for display.
|
|
24
|
+
*
|
|
25
|
+
* Removes all CYCLIST markers while preserving surrounding text.
|
|
26
|
+
* Useful for cleaning agent output before displaying to users.
|
|
27
|
+
*
|
|
28
|
+
* @param text - Text containing markers
|
|
29
|
+
* @returns Text with markers removed
|
|
30
|
+
*/
|
|
31
|
+
export function stripMarkers(text) {
|
|
32
|
+
if (!text) {
|
|
33
|
+
return '';
|
|
34
|
+
}
|
|
35
|
+
// Reset lastIndex since MARKER_PATTERN is global
|
|
36
|
+
MARKER_PATTERN.lastIndex = 0;
|
|
37
|
+
return text.replace(MARKER_PATTERN, '').trim();
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=strip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strip.js","sourceRoot":"","sources":["../../src/marker/strip.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,iDAAiD;IACjD,cAAc,CAAC,SAAS,GAAG,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the Reflector marker system.
|
|
3
|
+
*
|
|
4
|
+
* @see docs/adr/0011-reflector-marker-consolidation.md
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Marker types supported by the Reflector protocol.
|
|
8
|
+
* These map to UI actions in Cyclist and VS Code extension.
|
|
9
|
+
*/
|
|
10
|
+
export type MarkerType = 'handoff' | 'context_clear' | 'invoke' | 'question' | 'choices';
|
|
11
|
+
/**
|
|
12
|
+
* Parsed marker from agent output.
|
|
13
|
+
*
|
|
14
|
+
* @property type - The marker type (normalized to lowercase)
|
|
15
|
+
* @property value - The marker value (case preserved)
|
|
16
|
+
* @property source - Optional source identifier (always 'structured_marker' when detected)
|
|
17
|
+
*/
|
|
18
|
+
export interface Marker {
|
|
19
|
+
type: MarkerType;
|
|
20
|
+
value: string;
|
|
21
|
+
source?: 'structured_marker';
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/marker/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,MAAM,UAAU,GAClB,SAAS,GACT,eAAe,GACf,QAAQ,GACR,UAAU,GACV,SAAS,CAAC;AAEd;;;;;;GAMG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/marker/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Schema Migration Tests - MSSCI-12478
|
|
3
|
+
*
|
|
4
|
+
* Tests for the migration script that consolidates quote into catchphrases.
|
|
5
|
+
* RED STATE: These tests should FAIL until implementation is complete.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=migrate-theme-schema.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-theme-schema.test.d.ts","sourceRoot":"","sources":["../src/migrate-theme-schema.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Schema Migration Tests - MSSCI-12478
|
|
3
|
+
*
|
|
4
|
+
* Tests for the migration script that consolidates quote into catchphrases.
|
|
5
|
+
* RED STATE: These tests should FAIL until implementation is complete.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, before } from 'node:test';
|
|
8
|
+
import assert from 'node:assert';
|
|
9
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
10
|
+
import { join, dirname } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = dirname(__filename);
|
|
14
|
+
// Path to themes directory (relative to test location)
|
|
15
|
+
const THEMES_DIR = join(__dirname, '..', '..', '..', 'pennyfarthing-dist', 'personas', 'themes');
|
|
16
|
+
describe('MSSCI-12478: Theme YAML Migration', () => {
|
|
17
|
+
let themeFiles;
|
|
18
|
+
before(() => {
|
|
19
|
+
themeFiles = readdirSync(THEMES_DIR).filter(f => f.endsWith('.yaml'));
|
|
20
|
+
});
|
|
21
|
+
describe('AC2: All 102 themes updated', () => {
|
|
22
|
+
it('should have 102 theme files', () => {
|
|
23
|
+
assert.strictEqual(themeFiles.length, 102, `Expected 102 themes, got ${themeFiles.length}`);
|
|
24
|
+
});
|
|
25
|
+
it('no theme file should contain quote: field under agents', () => {
|
|
26
|
+
const themesWithQuote = [];
|
|
27
|
+
for (const file of themeFiles) {
|
|
28
|
+
const content = readFileSync(join(THEMES_DIR, file), 'utf-8');
|
|
29
|
+
// Check for quote: at 4-space indent (under agent definition)
|
|
30
|
+
if (/^ {4}quote:/m.test(content)) {
|
|
31
|
+
themesWithQuote.push(file);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
assert.strictEqual(themesWithQuote.length, 0, `These themes still have quote field: ${themesWithQuote.slice(0, 5).join(', ')}${themesWithQuote.length > 5 ? ` and ${themesWithQuote.length - 5} more` : ''}`);
|
|
35
|
+
});
|
|
36
|
+
it('every theme should have catchphrases array for each agent', () => {
|
|
37
|
+
const themesWithMissingCatchphrases = [];
|
|
38
|
+
for (const file of themeFiles) {
|
|
39
|
+
// Skip control.yaml which is a special baseline theme
|
|
40
|
+
if (file === 'control.yaml')
|
|
41
|
+
continue;
|
|
42
|
+
const content = readFileSync(join(THEMES_DIR, file), 'utf-8');
|
|
43
|
+
// Count catchphrases section markers (10 agents expected)
|
|
44
|
+
const catchphrasesMatches = content.match(/^ {4}catchphrases:/gm);
|
|
45
|
+
if (!catchphrasesMatches || catchphrasesMatches.length < 10) {
|
|
46
|
+
themesWithMissingCatchphrases.push(file);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
assert.strictEqual(themesWithMissingCatchphrases.length, 0, `These themes have missing catchphrases: ${themesWithMissingCatchphrases.slice(0, 5).join(', ')}${themesWithMissingCatchphrases.length > 5 ? ` and ${themesWithMissingCatchphrases.length - 5} more` : ''}`);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('AC1: Migration preserves original quote in catchphrases', () => {
|
|
53
|
+
it('the-expanse orchestrator catchphrases should contain original quote', () => {
|
|
54
|
+
const content = readFileSync(join(THEMES_DIR, 'the-expanse.yaml'), 'utf-8');
|
|
55
|
+
// Original quote was: "Doors and corners, kid. That's where they get you."
|
|
56
|
+
// This should now be in the catchphrases array
|
|
57
|
+
assert.ok(content.includes("Doors and corners, kid. That's where they get you."), 'Quote should still be present in file');
|
|
58
|
+
assert.ok(/catchphrases:[\s\S]*?Doors and corners/.test(content), 'Quote should be within catchphrases array, not as separate quote field');
|
|
59
|
+
});
|
|
60
|
+
it('star-trek-tng picard catchphrases should contain original quote', () => {
|
|
61
|
+
const content = readFileSync(join(THEMES_DIR, 'star-trek-tng.yaml'), 'utf-8');
|
|
62
|
+
// Picard's famous quote should be in catchphrases
|
|
63
|
+
assert.ok(/catchphrases:[\s\S]*?(Make it so|Engage)/.test(content), 'Picard quote should be within catchphrases array');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=migrate-theme-schema.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-theme-schema.test.js","sourceRoot":"","sources":["../src/migrate-theme-schema.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portrait Resolver - Smart path resolution for Pennyfarthing portraits
|
|
3
|
+
*
|
|
4
|
+
* Checks paths in priority order:
|
|
5
|
+
* 1. PENNYFARTHING_DIST env var (explicit override)
|
|
6
|
+
* 2. Monorepo root (pennyfarthing-dist/ at repo root for dogfooding)
|
|
7
|
+
* 3. Sibling directory (for dev scenarios)
|
|
8
|
+
* 4. Scoped npm (node_modules/@pennyfarthing/core/pennyfarthing-dist/)
|
|
9
|
+
* 5. Legacy npm (node_modules/pennyfarthing/pennyfarthing-dist/)
|
|
10
|
+
*/
|
|
11
|
+
export interface PortraitPaths {
|
|
12
|
+
portraitsDir: string;
|
|
13
|
+
themesDir: string;
|
|
14
|
+
agentsDir: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the pennyfarthing-dist directory path
|
|
18
|
+
* Checks multiple locations in priority order
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolvePennyfarthingDist(): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the full path to a portrait image
|
|
23
|
+
* @param theme - Theme name (e.g., 'shakespeare', 'norse-mythology')
|
|
24
|
+
* @param agent - Agent name (e.g., 'sm', 'tea', 'dev')
|
|
25
|
+
* @returns Full path to portrait file, or null if not found
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolvePortraitPath(theme: string, agent: string): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Get all portrait-related paths for a resolved dist directory
|
|
30
|
+
*/
|
|
31
|
+
export declare function getPortraitPaths(distPath: string): PortraitPaths;
|
|
32
|
+
//# sourceMappingURL=portrait-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portrait-resolver.d.ts","sourceRoot":"","sources":["../src/portrait-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,IAAI,CAgDxD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsE/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAShE"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portrait Resolver - Smart path resolution for Pennyfarthing portraits
|
|
3
|
+
*
|
|
4
|
+
* Checks paths in priority order:
|
|
5
|
+
* 1. PENNYFARTHING_DIST env var (explicit override)
|
|
6
|
+
* 2. Monorepo root (pennyfarthing-dist/ at repo root for dogfooding)
|
|
7
|
+
* 3. Sibling directory (for dev scenarios)
|
|
8
|
+
* 4. Scoped npm (node_modules/@pennyfarthing/core/pennyfarthing-dist/)
|
|
9
|
+
* 5. Legacy npm (node_modules/pennyfarthing/pennyfarthing-dist/)
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
12
|
+
import { join, dirname, resolve } from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
// Get the directory where this module is located
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = dirname(__filename);
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the pennyfarthing-dist directory path
|
|
19
|
+
* Checks multiple locations in priority order
|
|
20
|
+
*/
|
|
21
|
+
export function resolvePennyfarthingDist() {
|
|
22
|
+
// 1. PENNYFARTHING_DIST env var (explicit override)
|
|
23
|
+
const envPath = process.env.PENNYFARTHING_DIST;
|
|
24
|
+
if (envPath) {
|
|
25
|
+
if (existsSync(envPath)) {
|
|
26
|
+
return envPath;
|
|
27
|
+
}
|
|
28
|
+
// Env var set but path doesn't exist - fall through to other checks
|
|
29
|
+
}
|
|
30
|
+
// 2. Monorepo root (pennyfarthing-dist/ at repo root for dogfooding)
|
|
31
|
+
// Walk up from current directory looking for pennyfarthing-dist/
|
|
32
|
+
let currentDir = __dirname;
|
|
33
|
+
for (let i = 0; i < 10; i++) {
|
|
34
|
+
const monorepoPath = join(currentDir, 'pennyfarthing-dist');
|
|
35
|
+
if (existsSync(monorepoPath)) {
|
|
36
|
+
return monorepoPath;
|
|
37
|
+
}
|
|
38
|
+
const parentDir = dirname(currentDir);
|
|
39
|
+
if (parentDir === currentDir)
|
|
40
|
+
break; // Reached root
|
|
41
|
+
currentDir = parentDir;
|
|
42
|
+
}
|
|
43
|
+
// 3. Sibling directory (for dev scenarios)
|
|
44
|
+
// Check ../pennyfarthing-dist, ../../pennyfarthing-dist from module location
|
|
45
|
+
currentDir = __dirname;
|
|
46
|
+
for (let i = 0; i < 5; i++) {
|
|
47
|
+
currentDir = dirname(currentDir);
|
|
48
|
+
const siblingPath = join(currentDir, 'pennyfarthing-dist');
|
|
49
|
+
if (existsSync(siblingPath)) {
|
|
50
|
+
return siblingPath;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// 4. Scoped npm (node_modules/@pennyfarthing/core/pennyfarthing-dist/)
|
|
54
|
+
const scopedNpmPath = resolve(__dirname, '..', '..', '..', '@pennyfarthing', 'core', 'pennyfarthing-dist');
|
|
55
|
+
if (existsSync(scopedNpmPath)) {
|
|
56
|
+
return scopedNpmPath;
|
|
57
|
+
}
|
|
58
|
+
// 5. Legacy npm (node_modules/pennyfarthing/pennyfarthing-dist/)
|
|
59
|
+
const legacyNpmPath = resolve(__dirname, '..', '..', '..', 'pennyfarthing', 'pennyfarthing-dist');
|
|
60
|
+
if (existsSync(legacyNpmPath)) {
|
|
61
|
+
return legacyNpmPath;
|
|
62
|
+
}
|
|
63
|
+
// No valid path found
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
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
|
|
71
|
+
*/
|
|
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);
|
|
79
|
+
if (!existsSync(portraitsThemeDir)) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
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
|
+
try {
|
|
87
|
+
// Check size subdirectories in preference order
|
|
88
|
+
const sizeDirectories = ['large', 'medium', 'small', 'original'];
|
|
89
|
+
let files = [];
|
|
90
|
+
let searchDir = portraitsThemeDir;
|
|
91
|
+
for (const sizeDir of sizeDirectories) {
|
|
92
|
+
const sizedPath = join(portraitsThemeDir, sizeDir);
|
|
93
|
+
if (existsSync(sizedPath)) {
|
|
94
|
+
files = readdirSync(sizedPath);
|
|
95
|
+
searchDir = sizedPath;
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Fallback to root directory if no size subdirectories
|
|
100
|
+
if (files.length === 0) {
|
|
101
|
+
files = readdirSync(portraitsThemeDir);
|
|
102
|
+
searchDir = portraitsThemeDir;
|
|
103
|
+
}
|
|
104
|
+
// 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
|
+
const agentMappings = {
|
|
109
|
+
'sm': ['prospero', 'baldur', 'face', 'faceman', 'sm'],
|
|
110
|
+
'tea': ['hamlet', 'tyr', 'murdock', 'tea'],
|
|
111
|
+
'dev': ['puck', 'loki', 'ba', 'dev'],
|
|
112
|
+
'reviewer': ['portia', 'heimdall', 'lynch', 'decker', 'reviewer'],
|
|
113
|
+
'architect': ['oberon', 'mimir', 'hannibal', 'architect'],
|
|
114
|
+
'pm': ['henry', 'thor', 'amy', 'pm'],
|
|
115
|
+
'tech-writer': ['horatio', 'bragi', 'tech-writer'],
|
|
116
|
+
'ux-designer': ['viola', 'idunn', 'ux-designer'],
|
|
117
|
+
'devops': ['caliban', 'norns', 'devops'],
|
|
118
|
+
'orchestrator': ['chorus', 'odin', 'orchestrator'],
|
|
119
|
+
};
|
|
120
|
+
const possiblePrefixes = agentMappings[agent] || [agent];
|
|
121
|
+
for (const file of files) {
|
|
122
|
+
for (const prefix of possiblePrefixes) {
|
|
123
|
+
if (file.toLowerCase().startsWith(prefix.toLowerCase()) &&
|
|
124
|
+
(file.endsWith('.png') || file.endsWith('.jpg'))) {
|
|
125
|
+
return join(searchDir, file);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get all portrait-related paths for a resolved dist directory
|
|
137
|
+
*/
|
|
138
|
+
export function getPortraitPaths(distPath) {
|
|
139
|
+
// Normalize path to remove trailing slashes
|
|
140
|
+
const normalizedPath = distPath.replace(/\/+$/, '');
|
|
141
|
+
return {
|
|
142
|
+
portraitsDir: join(normalizedPath, 'personas', 'portraits'),
|
|
143
|
+
themesDir: join(normalizedPath, 'personas'),
|
|
144
|
+
agentsDir: join(normalizedPath, 'agents'),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=portrait-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portrait-resolver.js","sourceRoot":"","sources":["../src/portrait-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portrait-resolver.test.d.ts","sourceRoot":"","sources":["../src/portrait-resolver.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { describe, it, afterEach } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { resolvePennyfarthingDist, resolvePortraitPath, getPortraitPaths, } from './portrait-resolver.js';
|
|
5
|
+
describe('portrait-resolver', () => {
|
|
6
|
+
describe('resolvePennyfarthingDist', () => {
|
|
7
|
+
const originalEnv = process.env.PENNYFARTHING_DIST;
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
// Restore original env
|
|
10
|
+
if (originalEnv !== undefined) {
|
|
11
|
+
process.env.PENNYFARTHING_DIST = originalEnv;
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
delete process.env.PENNYFARTHING_DIST;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
it('should return PENNYFARTHING_DIST env var when set and path exists', () => {
|
|
18
|
+
// Scenario 1: Explicit env var override with existing path
|
|
19
|
+
// Use the actual pennyfarthing-dist path that exists
|
|
20
|
+
const actualDistPath = resolvePennyfarthingDist();
|
|
21
|
+
assert.ok(actualDistPath !== null, 'Should have a valid dist path');
|
|
22
|
+
process.env.PENNYFARTHING_DIST = actualDistPath;
|
|
23
|
+
const result = resolvePennyfarthingDist();
|
|
24
|
+
// When env var is set to valid existing path, should return it
|
|
25
|
+
assert.strictEqual(result, actualDistPath);
|
|
26
|
+
});
|
|
27
|
+
it('should fall through when PENNYFARTHING_DIST is set but path does not exist', () => {
|
|
28
|
+
// Scenario 1b: Env var set but invalid - should fall through to other checks
|
|
29
|
+
process.env.PENNYFARTHING_DIST = '/nonexistent/path/pennyfarthing-dist';
|
|
30
|
+
const result = resolvePennyfarthingDist();
|
|
31
|
+
// Should fall through and find monorepo path (since we're in monorepo)
|
|
32
|
+
// The key behavior is it doesn't return the invalid env var path
|
|
33
|
+
assert.ok(result === null || !result.includes('/nonexistent/'));
|
|
34
|
+
});
|
|
35
|
+
it('should find monorepo root pennyfarthing-dist directory', () => {
|
|
36
|
+
// Scenario 2: Monorepo root detection (dogfooding)
|
|
37
|
+
// When running from within pennyfarthing repo, find pennyfarthing-dist/ at root
|
|
38
|
+
delete process.env.PENNYFARTHING_DIST;
|
|
39
|
+
const result = resolvePennyfarthingDist();
|
|
40
|
+
// Should find the monorepo root path
|
|
41
|
+
assert.ok(result !== null, 'Should find monorepo root');
|
|
42
|
+
assert.ok(result.endsWith('pennyfarthing-dist'), 'Path should end with pennyfarthing-dist');
|
|
43
|
+
});
|
|
44
|
+
it('should find sibling pennyfarthing-dist directory', () => {
|
|
45
|
+
// Scenario 3: Sibling directory for dev scenarios
|
|
46
|
+
// e.g., project/pennyfarthing-dist when called from project/packages/shared
|
|
47
|
+
delete process.env.PENNYFARTHING_DIST;
|
|
48
|
+
const result = resolvePennyfarthingDist();
|
|
49
|
+
// Implementation should check ../pennyfarthing-dist, ../../pennyfarthing-dist, etc.
|
|
50
|
+
assert.ok(result === null || result.includes('pennyfarthing-dist'));
|
|
51
|
+
});
|
|
52
|
+
it('should find scoped npm package path', () => {
|
|
53
|
+
// Scenario 4: Scoped npm install
|
|
54
|
+
// node_modules/@pennyfarthing/core/pennyfarthing-dist/
|
|
55
|
+
delete process.env.PENNYFARTHING_DIST;
|
|
56
|
+
const result = resolvePennyfarthingDist();
|
|
57
|
+
// When installed via @pennyfarthing/core, should find that path
|
|
58
|
+
assert.ok(result === null || result.includes('pennyfarthing-dist'));
|
|
59
|
+
});
|
|
60
|
+
it('should find legacy npm package path', () => {
|
|
61
|
+
// Scenario 5: Legacy npm install
|
|
62
|
+
// node_modules/pennyfarthing/pennyfarthing-dist/
|
|
63
|
+
delete process.env.PENNYFARTHING_DIST;
|
|
64
|
+
const result = resolvePennyfarthingDist();
|
|
65
|
+
// When installed via pennyfarthing, should find that path
|
|
66
|
+
assert.ok(result === null || result.includes('pennyfarthing-dist'));
|
|
67
|
+
});
|
|
68
|
+
it('should return a valid path or null', () => {
|
|
69
|
+
// This tests that the function returns a valid result
|
|
70
|
+
delete process.env.PENNYFARTHING_DIST;
|
|
71
|
+
const result = resolvePennyfarthingDist();
|
|
72
|
+
// Result should be either null or a valid pennyfarthing-dist path
|
|
73
|
+
if (result !== null) {
|
|
74
|
+
assert.ok(result.includes('pennyfarthing-dist'));
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
it('should check paths in priority order - env var takes precedence', () => {
|
|
78
|
+
// When multiple paths exist, env var should return first if it exists
|
|
79
|
+
const actualDistPath = resolvePennyfarthingDist();
|
|
80
|
+
assert.ok(actualDistPath !== null, 'Should have a valid dist path');
|
|
81
|
+
// Set env var to actual path
|
|
82
|
+
process.env.PENNYFARTHING_DIST = actualDistPath;
|
|
83
|
+
const result = resolvePennyfarthingDist();
|
|
84
|
+
// Env var should take precedence (returns same path since it exists)
|
|
85
|
+
assert.strictEqual(result, actualDistPath);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('resolvePortraitPath', () => {
|
|
89
|
+
it('should resolve portrait path for valid theme and agent', () => {
|
|
90
|
+
// Use a-team which has actual portraits (shakespeare has only .gitkeep)
|
|
91
|
+
const result = resolvePortraitPath('a-team', 'sm');
|
|
92
|
+
assert.ok(result !== null, 'Should find portrait');
|
|
93
|
+
assert.ok(result.includes('a-team'), 'Path should include theme');
|
|
94
|
+
// Portrait files use character names (faceman) not agent names (sm)
|
|
95
|
+
assert.ok(result.includes('face'), 'Path should include character name');
|
|
96
|
+
assert.ok(result.endsWith('.png') || result.endsWith('.jpg'), 'Should be image file');
|
|
97
|
+
});
|
|
98
|
+
it('should return null for invalid theme', () => {
|
|
99
|
+
const result = resolvePortraitPath('nonexistent-theme', 'sm');
|
|
100
|
+
assert.strictEqual(result, null);
|
|
101
|
+
});
|
|
102
|
+
it('should return null for invalid agent', () => {
|
|
103
|
+
const result = resolvePortraitPath('a-team', 'nonexistent-agent');
|
|
104
|
+
assert.strictEqual(result, null);
|
|
105
|
+
});
|
|
106
|
+
it('should handle theme with special characters in name', () => {
|
|
107
|
+
// Themes like 'star-trek-tos' have hyphens
|
|
108
|
+
const result = resolvePortraitPath('star-trek-tos', 'sm');
|
|
109
|
+
assert.ok(result === null || result.includes('star-trek-tos'));
|
|
110
|
+
});
|
|
111
|
+
it('should handle portrait resolution when dist is found', () => {
|
|
112
|
+
// When resolvePennyfarthingDist returns a valid path, we should be able
|
|
113
|
+
// to resolve portraits for known themes
|
|
114
|
+
delete process.env.PENNYFARTHING_DIST;
|
|
115
|
+
const result = resolvePortraitPath('a-team', 'dev');
|
|
116
|
+
// If dist is found (which it is in monorepo), should find portrait
|
|
117
|
+
// dev maps to ba in a-team theme
|
|
118
|
+
if (result !== null) {
|
|
119
|
+
assert.ok(result.includes('a-team'));
|
|
120
|
+
assert.ok(result.includes('ba'));
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
describe('getPortraitPaths', () => {
|
|
125
|
+
it('should return correct paths structure', () => {
|
|
126
|
+
const distPath = '/test/pennyfarthing-dist';
|
|
127
|
+
const result = getPortraitPaths(distPath);
|
|
128
|
+
assert.ok('portraitsDir' in result, 'Should have portraitsDir');
|
|
129
|
+
assert.ok('themesDir' in result, 'Should have themesDir');
|
|
130
|
+
assert.ok('agentsDir' in result, 'Should have agentsDir');
|
|
131
|
+
});
|
|
132
|
+
it('should build portraitsDir correctly', () => {
|
|
133
|
+
const distPath = '/test/pennyfarthing-dist';
|
|
134
|
+
const result = getPortraitPaths(distPath);
|
|
135
|
+
// Actual structure: pennyfarthing-dist/personas/portraits/
|
|
136
|
+
assert.strictEqual(result.portraitsDir, path.join(distPath, 'personas', 'portraits'), 'portraitsDir should be distPath/personas/portraits');
|
|
137
|
+
});
|
|
138
|
+
it('should build themesDir correctly', () => {
|
|
139
|
+
const distPath = '/test/pennyfarthing-dist';
|
|
140
|
+
const result = getPortraitPaths(distPath);
|
|
141
|
+
assert.strictEqual(result.themesDir, path.join(distPath, 'personas'), 'themesDir should be distPath/personas');
|
|
142
|
+
});
|
|
143
|
+
it('should build agentsDir correctly', () => {
|
|
144
|
+
const distPath = '/test/pennyfarthing-dist';
|
|
145
|
+
const result = getPortraitPaths(distPath);
|
|
146
|
+
assert.strictEqual(result.agentsDir, path.join(distPath, 'agents'), 'agentsDir should be distPath/agents');
|
|
147
|
+
});
|
|
148
|
+
it('should handle paths with trailing slashes', () => {
|
|
149
|
+
const distPath = '/test/pennyfarthing-dist/';
|
|
150
|
+
const result = getPortraitPaths(distPath);
|
|
151
|
+
// Should normalize paths correctly
|
|
152
|
+
assert.ok(!result.portraitsDir.includes('//'), 'Should not have double slashes');
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
//# sourceMappingURL=portrait-resolver.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portrait-resolver.test.js","sourceRoot":"","sources":["../src/portrait-resolver.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Search Utility - Story 9-2
|
|
3
|
+
*
|
|
4
|
+
* Searches the skill registry by tag, keyword, category, or description query.
|
|
5
|
+
* Returns matching skills with metadata for discovery and suggestions.
|
|
6
|
+
*/
|
|
7
|
+
export interface SearchOptions {
|
|
8
|
+
/** Filter by tag (e.g., "tdd", "quality") */
|
|
9
|
+
tag?: string;
|
|
10
|
+
/** Filter by keyword (e.g., "jest", "vitest") */
|
|
11
|
+
keyword?: string;
|
|
12
|
+
/** Search description text */
|
|
13
|
+
query?: string;
|
|
14
|
+
/** Filter by category (e.g., "development", "tools") */
|
|
15
|
+
category?: string;
|
|
16
|
+
/** Custom path to registry file (for testing) */
|
|
17
|
+
registryPath?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SkillResult {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
category: string;
|
|
23
|
+
tags: string[];
|
|
24
|
+
keywords?: string[];
|
|
25
|
+
version?: string;
|
|
26
|
+
related_skills?: string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Search skills in the registry based on provided options.
|
|
30
|
+
*
|
|
31
|
+
* @param options - Search options (tag, keyword, query, category)
|
|
32
|
+
* @returns Promise resolving to array of matching skills
|
|
33
|
+
* @throws Error if registry file not found or invalid category
|
|
34
|
+
*/
|
|
35
|
+
export declare function searchSkills(options: SearchOptions): Promise<SkillResult[]>;
|
|
36
|
+
//# sourceMappingURL=skill-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-search.d.ts","sourceRoot":"","sources":["../src/skill-search.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAmLD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAoEjF"}
|