skillex 0.2.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.
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Structured output helpers for the Skillex CLI.
3
+ *
4
+ * Applies ANSI colors when stdout/stderr are TTYs and NO_COLOR is unset.
5
+ * Provides a verbose flag that gates debug-level output.
6
+ */
7
+ /**
8
+ * Enables or disables verbose (debug) output for the current process.
9
+ *
10
+ * @param value - `true` to enable verbose output.
11
+ */
12
+ export declare function setVerbose(value: boolean): void;
13
+ /**
14
+ * Returns whether verbose mode is currently active.
15
+ */
16
+ export declare function isVerbose(): boolean;
17
+ /**
18
+ * Prints a green success message to stdout.
19
+ *
20
+ * @param message - Message to display.
21
+ */
22
+ export declare function success(message: string): void;
23
+ /**
24
+ * Prints a plain informational message to stdout.
25
+ *
26
+ * @param message - Message to display.
27
+ */
28
+ export declare function info(message: string): void;
29
+ /**
30
+ * Prints a yellow warning to stderr.
31
+ *
32
+ * @param message - Warning message.
33
+ */
34
+ export declare function warn(message: string): void;
35
+ /**
36
+ * Prints a red error message to stderr.
37
+ *
38
+ * @param message - Error message.
39
+ */
40
+ export declare function error(message: string): void;
41
+ /**
42
+ * Prints a dim debug message to stderr when verbose mode is active.
43
+ *
44
+ * @param message - Debug message.
45
+ */
46
+ export declare function debug(message: string): void;
package/dist/output.js ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Structured output helpers for the Skillex CLI.
3
+ *
4
+ * Applies ANSI colors when stdout/stderr are TTYs and NO_COLOR is unset.
5
+ * Provides a verbose flag that gates debug-level output.
6
+ */
7
+ let verboseEnabled = false;
8
+ // ---------------------------------------------------------------------------
9
+ // Color support detection
10
+ // ---------------------------------------------------------------------------
11
+ function colorEnabled(stream) {
12
+ return Boolean(stream.isTTY) && process.env.NO_COLOR === undefined;
13
+ }
14
+ function applyColor(ansiCode, text, stream) {
15
+ return colorEnabled(stream) ? `\x1b[${ansiCode}m${text}\x1b[0m` : text;
16
+ }
17
+ // ---------------------------------------------------------------------------
18
+ // Verbose flag
19
+ // ---------------------------------------------------------------------------
20
+ /**
21
+ * Enables or disables verbose (debug) output for the current process.
22
+ *
23
+ * @param value - `true` to enable verbose output.
24
+ */
25
+ export function setVerbose(value) {
26
+ verboseEnabled = value;
27
+ }
28
+ /**
29
+ * Returns whether verbose mode is currently active.
30
+ */
31
+ export function isVerbose() {
32
+ return verboseEnabled;
33
+ }
34
+ // ---------------------------------------------------------------------------
35
+ // Output helpers
36
+ // ---------------------------------------------------------------------------
37
+ /**
38
+ * Prints a green success message to stdout.
39
+ *
40
+ * @param message - Message to display.
41
+ */
42
+ export function success(message) {
43
+ console.log(applyColor("32", message, process.stdout));
44
+ }
45
+ /**
46
+ * Prints a plain informational message to stdout.
47
+ *
48
+ * @param message - Message to display.
49
+ */
50
+ export function info(message) {
51
+ console.log(message);
52
+ }
53
+ /**
54
+ * Prints a yellow warning to stderr.
55
+ *
56
+ * @param message - Warning message.
57
+ */
58
+ export function warn(message) {
59
+ console.warn(applyColor("33", `Warning: ${message}`, process.stderr));
60
+ }
61
+ /**
62
+ * Prints a red error message to stderr.
63
+ *
64
+ * @param message - Error message.
65
+ */
66
+ export function error(message) {
67
+ console.error(applyColor("31", message, process.stderr));
68
+ }
69
+ /**
70
+ * Prints a dim debug message to stderr when verbose mode is active.
71
+ *
72
+ * @param message - Debug message.
73
+ */
74
+ export function debug(message) {
75
+ if (verboseEnabled) {
76
+ process.stderr.write(applyColor("2", `[debug] ${message}`, process.stderr) + "\n");
77
+ }
78
+ }
@@ -0,0 +1,31 @@
1
+ import type { Writable } from "node:stream";
2
+ import type { ProjectOptions } from "./types.js";
3
+ interface RunSkillOptions extends ProjectOptions {
4
+ yes?: boolean | undefined;
5
+ timeout?: number | undefined;
6
+ confirm?: (() => Promise<boolean>) | undefined;
7
+ stdout?: Writable | undefined;
8
+ stderr?: Writable | undefined;
9
+ }
10
+ /**
11
+ * Parses a `skill-id:command` reference used by the `run` command.
12
+ *
13
+ * @param value - User-supplied run target.
14
+ * @returns Parsed skill id and command name.
15
+ * @throws {CliError} When the reference is invalid.
16
+ */
17
+ export declare function parseSkillCommandReference(value: string): {
18
+ skillId: string;
19
+ command: string;
20
+ };
21
+ /**
22
+ * Executes a named script declared in an installed skill manifest.
23
+ *
24
+ * @param skillId - Installed skill identifier.
25
+ * @param commandName - Script name from the local `skill.json`.
26
+ * @param options - Execution options.
27
+ * @returns Child process exit code.
28
+ * @throws {CliError} When the skill or command is unavailable.
29
+ */
30
+ export declare function runSkillScript(skillId: string, commandName: string, options?: RunSkillOptions): Promise<number>;
31
+ export {};
package/dist/runner.js ADDED
@@ -0,0 +1,94 @@
1
+ import { spawn } from "node:child_process";
2
+ import * as path from "node:path";
3
+ import { DEFAULT_AGENT_SKILLS_DIR, getStatePaths } from "./config.js";
4
+ import { confirmAction } from "./confirm.js";
5
+ import { readJson } from "./fs.js";
6
+ import { CliError } from "./types.js";
7
+ /**
8
+ * Parses a `skill-id:command` reference used by the `run` command.
9
+ *
10
+ * @param value - User-supplied run target.
11
+ * @returns Parsed skill id and command name.
12
+ * @throws {CliError} When the reference is invalid.
13
+ */
14
+ export function parseSkillCommandReference(value) {
15
+ const separatorIndex = value.indexOf(":");
16
+ if (separatorIndex <= 0 || separatorIndex === value.length - 1) {
17
+ throw new CliError('Use o formato "skill-id:comando" para executar scripts.', "INVALID_RUN_REFERENCE");
18
+ }
19
+ return {
20
+ skillId: value.slice(0, separatorIndex),
21
+ command: value.slice(separatorIndex + 1),
22
+ };
23
+ }
24
+ /**
25
+ * Executes a named script declared in an installed skill manifest.
26
+ *
27
+ * @param skillId - Installed skill identifier.
28
+ * @param commandName - Script name from the local `skill.json`.
29
+ * @param options - Execution options.
30
+ * @returns Child process exit code.
31
+ * @throws {CliError} When the skill or command is unavailable.
32
+ */
33
+ export async function runSkillScript(skillId, commandName, options = {}) {
34
+ const cwd = options.cwd || process.cwd();
35
+ const statePaths = getStatePaths(cwd, options.agentSkillsDir || DEFAULT_AGENT_SKILLS_DIR);
36
+ const lockfile = (await readJson(statePaths.lockfilePath, null)) || null;
37
+ if (!lockfile) {
38
+ throw new CliError("Nenhuma instalacao local encontrada. Rode: skillex init", "LOCKFILE_MISSING");
39
+ }
40
+ const metadata = lockfile.installed?.[skillId];
41
+ if (!metadata?.path) {
42
+ throw new CliError(`Skill "${skillId}" nao esta instalada.`, "SKILL_NOT_INSTALLED");
43
+ }
44
+ const skillDir = path.resolve(cwd, metadata.path);
45
+ const manifest = (await readJson(path.join(skillDir, "skill.json"), {})) || {};
46
+ const scripts = manifest.scripts || {};
47
+ const script = scripts[commandName];
48
+ if (!script) {
49
+ const available = Object.keys(scripts);
50
+ throw new CliError(available.length > 0
51
+ ? `Comando "${commandName}" nao existe para "${skillId}". Disponiveis: ${available.join(", ")}`
52
+ : `A skill "${skillId}" nao declara scripts executaveis.`, "RUN_COMMAND_NOT_FOUND");
53
+ }
54
+ const confirm = options.confirm || (() => confirmAction(`Executar em ${skillId}: ${script}?`));
55
+ if (!options.yes) {
56
+ const accepted = await confirm();
57
+ if (!accepted) {
58
+ throw new CliError("Execucao cancelada pelo usuario.", "RUN_CANCELLED");
59
+ }
60
+ }
61
+ const stdout = options.stdout || process.stdout;
62
+ const stderr = options.stderr || process.stderr;
63
+ const timeoutSeconds = options.timeout || 30;
64
+ const timeoutMs = timeoutSeconds * 1000;
65
+ return new Promise((resolve, reject) => {
66
+ let timedOut = false;
67
+ const child = spawn(script, {
68
+ cwd: skillDir,
69
+ env: process.env,
70
+ shell: true,
71
+ stdio: ["ignore", "pipe", "pipe"],
72
+ });
73
+ child.stdout?.on("data", (chunk) => {
74
+ stdout.write(chunk);
75
+ });
76
+ child.stderr?.on("data", (chunk) => {
77
+ stderr.write(chunk);
78
+ });
79
+ child.on("error", reject);
80
+ const timeout = setTimeout(() => {
81
+ timedOut = true;
82
+ child.kill("SIGTERM");
83
+ }, timeoutMs);
84
+ child.on("close", (code) => {
85
+ clearTimeout(timeout);
86
+ if (timedOut) {
87
+ stderr.write(`Tempo limite excedido (${timeoutSeconds}s).\n`);
88
+ resolve(1);
89
+ return;
90
+ }
91
+ resolve(code ?? 0);
92
+ });
93
+ });
94
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Parsed frontmatter values supported by Skillex skills.
3
+ */
4
+ export interface SkillFrontmatter {
5
+ name?: string | undefined;
6
+ description?: string | undefined;
7
+ autoInject?: boolean | undefined;
8
+ activationPrompt?: string | undefined;
9
+ }
10
+ /**
11
+ * Parses the YAML-like frontmatter at the top of a `SKILL.md` file.
12
+ *
13
+ * @param content - Raw markdown content.
14
+ * @returns Parsed frontmatter fields relevant to Skillex.
15
+ */
16
+ export declare function parseSkillFrontmatter(content: string): SkillFrontmatter;
17
+ /**
18
+ * Removes supported frontmatter and the top-level heading from a skill document.
19
+ *
20
+ * @param content - Raw markdown content.
21
+ * @returns Normalized markdown body.
22
+ */
23
+ export declare function normalizeSkillContent(content: string): string;
package/dist/skill.js ADDED
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Parses the YAML-like frontmatter at the top of a `SKILL.md` file.
3
+ *
4
+ * @param content - Raw markdown content.
5
+ * @returns Parsed frontmatter fields relevant to Skillex.
6
+ */
7
+ export function parseSkillFrontmatter(content) {
8
+ const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
9
+ if (!match || match[1] === undefined) {
10
+ return {};
11
+ }
12
+ const values = {};
13
+ for (const rawLine of match[1].split("\n")) {
14
+ const line = rawLine.trim();
15
+ if (!line || line.startsWith("#")) {
16
+ continue;
17
+ }
18
+ const separatorIndex = line.indexOf(":");
19
+ if (separatorIndex <= 0) {
20
+ continue;
21
+ }
22
+ const key = line.slice(0, separatorIndex).trim();
23
+ const rawValue = line.slice(separatorIndex + 1).trim();
24
+ const value = normalizeFrontmatterValue(rawValue);
25
+ if (key === "name" && typeof value === "string") {
26
+ values.name = value;
27
+ }
28
+ if (key === "description" && typeof value === "string") {
29
+ values.description = value;
30
+ }
31
+ if (key === "autoInject" && typeof value === "boolean") {
32
+ values.autoInject = value;
33
+ }
34
+ if (key === "activationPrompt" && typeof value === "string") {
35
+ values.activationPrompt = value;
36
+ }
37
+ }
38
+ return values;
39
+ }
40
+ /**
41
+ * Removes supported frontmatter and the top-level heading from a skill document.
42
+ *
43
+ * @param content - Raw markdown content.
44
+ * @returns Normalized markdown body.
45
+ */
46
+ export function normalizeSkillContent(content) {
47
+ const withoutFrontmatter = content.replace(/^---\s*\n[\s\S]*?\n---\s*\n?/, "");
48
+ const withoutTopHeading = withoutFrontmatter.replace(/^#\s+.+\n+/, "");
49
+ return withoutTopHeading.trim();
50
+ }
51
+ function normalizeFrontmatterValue(value) {
52
+ const trimmed = value.trim().replace(/^["']|["']$/g, "");
53
+ const normalized = trimmed.toLowerCase();
54
+ if (normalized === "true") {
55
+ return true;
56
+ }
57
+ if (normalized === "false") {
58
+ return false;
59
+ }
60
+ return trimmed;
61
+ }
package/dist/sync.d.ts ADDED
@@ -0,0 +1,41 @@
1
+ import type { InstalledSkillDocument, LockfileState, PreparedSyncResult, SyncOptions, SyncResult } from "./types.js";
2
+ /**
3
+ * Loads installed skill documents from the local workspace state directory.
4
+ *
5
+ * @param context - Workspace root and lockfile context.
6
+ * @returns Installed skill documents used for sync rendering.
7
+ */
8
+ export declare function loadInstalledSkillDocuments(context: {
9
+ cwd: string;
10
+ lockfile: LockfileState;
11
+ }): Promise<InstalledSkillDocument[]>;
12
+ /**
13
+ * Synchronizes installed skills into the target file consumed by an adapter.
14
+ *
15
+ * @param options - Sync execution options.
16
+ * @returns Final sync result.
17
+ * @throws {SyncError} When sync preparation or file writing fails.
18
+ */
19
+ export declare function syncAdapterFiles(options: SyncOptions): Promise<SyncResult>;
20
+ /**
21
+ * Prepares the next sync state without writing files.
22
+ *
23
+ * @param options - Sync preparation options.
24
+ * @returns Prepared sync state with before/after content and diff.
25
+ * @throws {SyncError} When the adapter cannot be prepared.
26
+ */
27
+ export declare function prepareSyncAdapterFiles(options: Omit<SyncOptions, "dryRun">): Promise<PreparedSyncResult>;
28
+ /**
29
+ * Renders installed skills into a single markdown document.
30
+ *
31
+ * @param skills - Installed skill documents.
32
+ * @returns Consolidated markdown body.
33
+ */
34
+ export declare function renderInstalledSkills(skills: InstalledSkillDocument[]): string;
35
+ /**
36
+ * Builds the managed auto-inject block for all installed skills that request it.
37
+ *
38
+ * @param skills - Installed skill documents.
39
+ * @returns Managed auto-inject block or `null` when nothing should be injected.
40
+ */
41
+ export declare function buildAutoInjectBlock(skills: InstalledSkillDocument[]): string | null;