@testspectra/skills 1.1.10 → 1.1.11-rc.3
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/commands/add.js +2 -1
- package/dist/commands/init.js +4 -1
- package/dist/commands/list.js +3 -2
- package/dist/commands/remove.js +4 -1
- package/dist/commands/update.js +29 -7
- package/dist/detector.d.ts +15 -0
- package/dist/detector.js +51 -9
- package/package.json +1 -1
package/dist/commands/add.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// oxlint-disable no-console
|
|
2
2
|
import { intro, outro, multiselect, isCancel, cancel } from '@clack/prompts';
|
|
3
|
-
import { installSkill } from '../detector.js';
|
|
3
|
+
import { installSkill, addConfiguredSkills } from '../detector.js';
|
|
4
4
|
import { loadAllSkills, getSkill } from '../registry.js';
|
|
5
5
|
export async function addSkills(skillIds, baseDir = process.cwd(), agentIds) {
|
|
6
6
|
intro('\x1b[1m\x1b[36m➕ Install TestSpectra Script-Authoring Skills\x1b[0m');
|
|
@@ -36,6 +36,7 @@ export async function addSkills(skillIds, baseDir = process.cwd(), agentIds) {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
if (installedList.length > 0) {
|
|
39
|
+
addConfiguredSkills(baseDir, installedList);
|
|
39
40
|
outro(`\x1b[32mSuccessfully installed ${installedList.length} skill(s)!\x1b[0m`);
|
|
40
41
|
}
|
|
41
42
|
else {
|
package/dist/commands/init.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// oxlint-disable no-console
|
|
2
2
|
import { intro, outro, multiselect, isCancel, cancel } from '@clack/prompts';
|
|
3
|
-
import { KNOWN_AGENTS, writeAgentConfig, installSkill } from '../detector.js';
|
|
3
|
+
import { KNOWN_AGENTS, writeAgentConfig, installSkill, addConfiguredSkills } from '../detector.js';
|
|
4
4
|
import { loadAllSkills, getSkill } from '../registry.js';
|
|
5
5
|
export async function initSkills(baseDir = process.cwd()) {
|
|
6
6
|
intro('\x1b[1m\x1b[36m🧭 TestSpectra Skills Setup\x1b[0m');
|
|
@@ -50,5 +50,8 @@ export async function initSkills(baseDir = process.cwd()) {
|
|
|
50
50
|
console.log(` \x1b[32m✔\x1b[0m Installed \x1b[1m${skill.id}\x1b[0m -> \x1b[2m${p}\x1b[0m`);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
+
if (installedList.length > 0) {
|
|
54
|
+
addConfiguredSkills(baseDir, installedList);
|
|
55
|
+
}
|
|
53
56
|
outro(`\x1b[32mSetup complete!\x1b[0m Installed ${installedList.length} skill(s) for agent(s): ${agentIds.join(', ')}.`);
|
|
54
57
|
}
|
package/dist/commands/list.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// oxlint-disable no-console
|
|
2
2
|
import { intro, outro } from '@clack/prompts';
|
|
3
|
-
import { getAgentSkillDirs, isSkillInstalled } from '../detector.js';
|
|
3
|
+
import { getAgentSkillDirs, isSkillInstalled, readConfiguredSkills } from '../detector.js';
|
|
4
4
|
import { loadAllSkills } from '../registry.js';
|
|
5
5
|
export function listSkills(baseDir = process.cwd(), agentIds) {
|
|
6
6
|
intro('\x1b[1m\x1b[36m📦 TestSpectra Skills Registry\x1b[0m');
|
|
7
7
|
const allSkills = loadAllSkills();
|
|
8
8
|
const targetDirs = getAgentSkillDirs(baseDir, agentIds);
|
|
9
|
+
const configured = new Set(readConfiguredSkills(baseDir) ?? []);
|
|
9
10
|
if (allSkills.length === 0) {
|
|
10
11
|
console.log('No skills found in registry.');
|
|
11
12
|
outro('Done.');
|
|
@@ -13,7 +14,7 @@ export function listSkills(baseDir = process.cwd(), agentIds) {
|
|
|
13
14
|
}
|
|
14
15
|
console.log(`\nAgent directories: \x1b[2m${targetDirs.join(', ')}\x1b[0m\n`);
|
|
15
16
|
for (const skill of allSkills) {
|
|
16
|
-
const installed = isSkillInstalled(skill.id, baseDir, agentIds);
|
|
17
|
+
const installed = configured.has(skill.id) || isSkillInstalled(skill.id, baseDir, agentIds);
|
|
17
18
|
const statusBadge = installed ? '\x1b[32m[Installed]\x1b[0m' : '\x1b[90m[Available]\x1b[0m';
|
|
18
19
|
console.log(` ${statusBadge} \x1b[1m${skill.id}\x1b[0m`);
|
|
19
20
|
console.log(` \x1b[90m${skill.description}\x1b[0m\n`);
|
package/dist/commands/remove.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// oxlint-disable no-console
|
|
2
2
|
import { intro, outro } from '@clack/prompts';
|
|
3
|
-
import { removeSkill } from '../detector.js';
|
|
3
|
+
import { removeSkill, removeConfiguredSkills } from '../detector.js';
|
|
4
4
|
export function removeSkills(skillIds, baseDir = process.cwd(), agentIds) {
|
|
5
5
|
intro('\x1b[1m\x1b[31m🗑️ Remove TestSpectra Skills\x1b[0m');
|
|
6
6
|
const targets = skillIds.filter(Boolean);
|
|
@@ -22,5 +22,8 @@ export function removeSkills(skillIds, baseDir = process.cwd(), agentIds) {
|
|
|
22
22
|
console.log(` \x1b[90m- Skill "${id}" was not installed.\x1b[0m`);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
+
if (removedList.length > 0) {
|
|
26
|
+
removeConfiguredSkills(baseDir, removedList);
|
|
27
|
+
}
|
|
25
28
|
outro(`\x1b[32mCompleted. Removed ${removedList.length} skill(s).\x1b[0m`);
|
|
26
29
|
}
|
package/dist/commands/update.js
CHANGED
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
// oxlint-disable no-console
|
|
2
2
|
import { intro, outro } from '@clack/prompts';
|
|
3
|
-
import { getInstalledSkills, installSkill } from '../detector.js';
|
|
4
|
-
import { getSkill } from '../registry.js';
|
|
3
|
+
import { addConfiguredSkills, getInstalledSkills, installSkill, readConfiguredSkills } from '../detector.js';
|
|
4
|
+
import { getSkill, loadAllSkills } from '../registry.js';
|
|
5
5
|
export function updateSkills(skillIds = [], baseDir = process.cwd(), agentIds) {
|
|
6
6
|
intro('\x1b[1m\x1b[36m🔄 Update TestSpectra Skills\x1b[0m');
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const allSkills = loadAllSkills();
|
|
8
|
+
const knownSkillIds = new Set(allSkills.map((s) => s.id));
|
|
9
|
+
const explicitTargets = skillIds.filter(Boolean);
|
|
10
|
+
const isExplicit = explicitTargets.length > 0;
|
|
11
|
+
// Determine which skills to update:
|
|
12
|
+
// 1. Explicit skill IDs if provided
|
|
13
|
+
// 2. Configured skill IDs from .spectra-skills.json (filtered against registry)
|
|
14
|
+
// 3. Fallback to installed directory detection (filtered against registry)
|
|
15
|
+
let targets;
|
|
16
|
+
if (isExplicit) {
|
|
17
|
+
targets = explicitTargets;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
const configuredSkills = readConfiguredSkills(baseDir);
|
|
21
|
+
if (configuredSkills && configuredSkills.length > 0) {
|
|
22
|
+
targets = configuredSkills.filter((id) => knownSkillIds.has(id));
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
targets = getInstalledSkills(baseDir, agentIds).filter((id) => knownSkillIds.has(id));
|
|
26
|
+
}
|
|
10
27
|
}
|
|
11
28
|
if (targets.length === 0) {
|
|
12
|
-
console.log('No installed skills found in project to update.');
|
|
29
|
+
console.log('No installed TestSpectra skills found in project to update.');
|
|
13
30
|
outro('Done.');
|
|
14
31
|
return;
|
|
15
32
|
}
|
|
@@ -17,7 +34,9 @@ export function updateSkills(skillIds = [], baseDir = process.cwd(), agentIds) {
|
|
|
17
34
|
for (const id of targets) {
|
|
18
35
|
const skill = getSkill(id);
|
|
19
36
|
if (!skill) {
|
|
20
|
-
|
|
37
|
+
if (isExplicit) {
|
|
38
|
+
console.log(`\x1b[33m⚠️ Skill "${id}" not found in current registry.\x1b[0m`);
|
|
39
|
+
}
|
|
21
40
|
continue;
|
|
22
41
|
}
|
|
23
42
|
const paths = installSkill(skill, baseDir, agentIds);
|
|
@@ -26,5 +45,8 @@ export function updateSkills(skillIds = [], baseDir = process.cwd(), agentIds) {
|
|
|
26
45
|
console.log(` \x1b[32m✔\x1b[0m Updated \x1b[1m${skill.id}\x1b[0m -> \x1b[2m${p}\x1b[0m`);
|
|
27
46
|
}
|
|
28
47
|
}
|
|
48
|
+
if (updatedList.length > 0) {
|
|
49
|
+
addConfiguredSkills(baseDir, updatedList);
|
|
50
|
+
}
|
|
29
51
|
outro(`\x1b[32mSuccessfully updated ${updatedList.length} skill(s)!\x1b[0m`);
|
|
30
52
|
}
|
package/dist/detector.d.ts
CHANGED
|
@@ -10,10 +10,25 @@ export interface AgentDefinition {
|
|
|
10
10
|
*/
|
|
11
11
|
export declare const KNOWN_AGENTS: AgentDefinition[];
|
|
12
12
|
export declare function getKnownAgentIds(): string[];
|
|
13
|
+
export declare const CONFIG_FILENAME = ".spectra-skills.json";
|
|
14
|
+
export interface SkillsConfig {
|
|
15
|
+
agents?: string[];
|
|
16
|
+
skills?: string[];
|
|
17
|
+
}
|
|
18
|
+
/** Reads the skills and agent selection persisted in `.spectra-skills.json`, if any. */
|
|
19
|
+
export declare function readSkillsConfig(baseDir?: string): SkillsConfig;
|
|
20
|
+
/** Persists partial skills configuration in `.spectra-skills.json`. */
|
|
21
|
+
export declare function writeSkillsConfig(baseDir: string, patch: Partial<SkillsConfig>): string;
|
|
13
22
|
/** Reads the agent selection persisted by `spectra-skills init`, if any. */
|
|
14
23
|
export declare function readAgentConfig(baseDir?: string): string[] | undefined;
|
|
15
24
|
/** Persists the agent selection chosen via `spectra-skills init` for future add/update/remove/list calls. */
|
|
16
25
|
export declare function writeAgentConfig(baseDir: string, agentIds: string[]): string;
|
|
26
|
+
/** Reads the installed skill IDs recorded in `.spectra-skills.json`, if any. */
|
|
27
|
+
export declare function readConfiguredSkills(baseDir?: string): string[] | undefined;
|
|
28
|
+
/** Adds skill IDs to `.spectra-skills.json`. */
|
|
29
|
+
export declare function addConfiguredSkills(baseDir: string, skillIds: string[]): void;
|
|
30
|
+
/** Removes skill IDs from `.spectra-skills.json`. */
|
|
31
|
+
export declare function removeConfiguredSkills(baseDir: string, skillIds: string[]): void;
|
|
17
32
|
/** Splits a comma/whitespace separated --agent value and reports any id not in KNOWN_AGENTS. */
|
|
18
33
|
export declare function resolveAgentSelection(raw?: string): {
|
|
19
34
|
ids: string[];
|
package/dist/detector.js
CHANGED
|
@@ -19,28 +19,70 @@ export const KNOWN_AGENTS = [
|
|
|
19
19
|
export function getKnownAgentIds() {
|
|
20
20
|
return KNOWN_AGENTS.map((a) => a.id);
|
|
21
21
|
}
|
|
22
|
-
const CONFIG_FILENAME = '.spectra-skills.json';
|
|
23
|
-
/** Reads the agent selection persisted
|
|
24
|
-
export function
|
|
22
|
+
export const CONFIG_FILENAME = '.spectra-skills.json';
|
|
23
|
+
/** Reads the skills and agent selection persisted in `.spectra-skills.json`, if any. */
|
|
24
|
+
export function readSkillsConfig(baseDir = process.cwd()) {
|
|
25
25
|
const configPath = path.join(baseDir, CONFIG_FILENAME);
|
|
26
26
|
if (!fs.existsSync(configPath))
|
|
27
|
-
return
|
|
27
|
+
return {};
|
|
28
28
|
try {
|
|
29
29
|
const parsed = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
30
30
|
const known = new Set(getKnownAgentIds());
|
|
31
31
|
const agents = (parsed.agents ?? []).filter((id) => known.has(id));
|
|
32
|
-
|
|
32
|
+
const skills = Array.isArray(parsed.skills) ? parsed.skills.filter(Boolean) : undefined;
|
|
33
|
+
return {
|
|
34
|
+
agents: agents.length > 0 ? agents : undefined,
|
|
35
|
+
skills,
|
|
36
|
+
};
|
|
33
37
|
}
|
|
34
38
|
catch {
|
|
35
|
-
return
|
|
39
|
+
return {};
|
|
36
40
|
}
|
|
37
41
|
}
|
|
38
|
-
/** Persists
|
|
39
|
-
export function
|
|
42
|
+
/** Persists partial skills configuration in `.spectra-skills.json`. */
|
|
43
|
+
export function writeSkillsConfig(baseDir, patch) {
|
|
40
44
|
const configPath = path.join(baseDir, CONFIG_FILENAME);
|
|
41
|
-
|
|
45
|
+
const existing = readSkillsConfig(baseDir);
|
|
46
|
+
const updated = {
|
|
47
|
+
agents: patch.agents !== undefined ? patch.agents : existing.agents,
|
|
48
|
+
skills: patch.skills !== undefined ? patch.skills : existing.skills,
|
|
49
|
+
};
|
|
50
|
+
const out = {};
|
|
51
|
+
if (updated.agents && updated.agents.length > 0)
|
|
52
|
+
out.agents = updated.agents;
|
|
53
|
+
if (updated.skills && updated.skills.length > 0)
|
|
54
|
+
out.skills = updated.skills;
|
|
55
|
+
fs.writeFileSync(configPath, JSON.stringify(out, null, 2) + '\n', 'utf-8');
|
|
42
56
|
return configPath;
|
|
43
57
|
}
|
|
58
|
+
/** Reads the agent selection persisted by `spectra-skills init`, if any. */
|
|
59
|
+
export function readAgentConfig(baseDir = process.cwd()) {
|
|
60
|
+
return readSkillsConfig(baseDir).agents;
|
|
61
|
+
}
|
|
62
|
+
/** Persists the agent selection chosen via `spectra-skills init` for future add/update/remove/list calls. */
|
|
63
|
+
export function writeAgentConfig(baseDir, agentIds) {
|
|
64
|
+
return writeSkillsConfig(baseDir, { agents: agentIds });
|
|
65
|
+
}
|
|
66
|
+
/** Reads the installed skill IDs recorded in `.spectra-skills.json`, if any. */
|
|
67
|
+
export function readConfiguredSkills(baseDir = process.cwd()) {
|
|
68
|
+
return readSkillsConfig(baseDir).skills;
|
|
69
|
+
}
|
|
70
|
+
/** Adds skill IDs to `.spectra-skills.json`. */
|
|
71
|
+
export function addConfiguredSkills(baseDir, skillIds) {
|
|
72
|
+
const existing = new Set(readConfiguredSkills(baseDir) ?? []);
|
|
73
|
+
for (const id of skillIds) {
|
|
74
|
+
existing.add(id);
|
|
75
|
+
}
|
|
76
|
+
writeSkillsConfig(baseDir, { skills: Array.from(existing).sort() });
|
|
77
|
+
}
|
|
78
|
+
/** Removes skill IDs from `.spectra-skills.json`. */
|
|
79
|
+
export function removeConfiguredSkills(baseDir, skillIds) {
|
|
80
|
+
const existing = new Set(readConfiguredSkills(baseDir) ?? []);
|
|
81
|
+
for (const id of skillIds) {
|
|
82
|
+
existing.delete(id);
|
|
83
|
+
}
|
|
84
|
+
writeSkillsConfig(baseDir, { skills: Array.from(existing).sort() });
|
|
85
|
+
}
|
|
44
86
|
/** Splits a comma/whitespace separated --agent value and reports any id not in KNOWN_AGENTS. */
|
|
45
87
|
export function resolveAgentSelection(raw) {
|
|
46
88
|
if (!raw)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testspectra/skills",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.11-rc.3",
|
|
4
4
|
"description": "Installer & manager for modular AI agent skills that standardize TestSpectra script authoring (specs, page objects, steps, actions, hooks, fixtures, matchers)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|