summaryrefslogtreecommitdiffhomepage
path: root/packages/skills/src/pure.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/skills/src/pure.ts')
-rw-r--r--packages/skills/src/pure.ts106
1 files changed, 53 insertions, 53 deletions
diff --git a/packages/skills/src/pure.ts b/packages/skills/src/pure.ts
index 2800967..4cc8e5c 100644
--- a/packages/skills/src/pure.ts
+++ b/packages/skills/src/pure.ts
@@ -5,14 +5,14 @@
/** A discovered skill entry (name + optional summary from metadata). */
export interface SkillEntry {
- readonly name: string;
- readonly summary?: string | undefined;
+ readonly name: string;
+ readonly summary?: string | undefined;
}
/** Result of parsing a skill file's metadata. */
export interface SkillMeta {
- readonly summary?: string | undefined;
- readonly hasMeta: boolean;
+ readonly summary?: string | undefined;
+ readonly hasMeta: boolean;
}
/**
@@ -22,16 +22,16 @@ export interface SkillMeta {
* Returns `{ hasMeta: false }` when line 2 is not `---` (malformed).
*/
export function parseSkillMeta(content: string): SkillMeta {
- const lines = content.split("\n");
- if (lines.length < 2) {
- return { hasMeta: false };
- }
- const line2 = lines[1];
- if (line2 === undefined || line2.trim() !== "---") {
- return { hasMeta: false };
- }
- const summary = lines[0];
- return { hasMeta: true, summary: summary?.trim() === "" ? undefined : summary };
+ const lines = content.split("\n");
+ if (lines.length < 2) {
+ return { hasMeta: false };
+ }
+ const line2 = lines[1];
+ if (line2 === undefined || line2.trim() !== "---") {
+ return { hasMeta: false };
+ }
+ const summary = lines[0];
+ return { hasMeta: true, summary: summary?.trim() === "" ? undefined : summary };
}
/**
@@ -40,11 +40,11 @@ export function parseSkillMeta(content: string): SkillMeta {
* When hasMeta is false, returns the whole file unchanged.
*/
export function stripLoadedBody(content: string, hasMeta: boolean): string {
- if (!hasMeta) {
- return content;
- }
- const lines = content.split("\n");
- return lines.slice(2).join("\n");
+ if (!hasMeta) {
+ return content;
+ }
+ const lines = content.split("\n");
+ return lines.slice(2).join("\n");
}
/**
@@ -52,17 +52,17 @@ export function stripLoadedBody(content: string, hasMeta: boolean): string {
* Returns a deduplicated array sorted by name.
*/
export function mergeCatalog(
- homeEntries: readonly SkillEntry[],
- cwdEntries: readonly SkillEntry[],
+ homeEntries: readonly SkillEntry[],
+ cwdEntries: readonly SkillEntry[],
): readonly SkillEntry[] {
- const map = new Map<string, SkillEntry>();
- for (const entry of homeEntries) {
- map.set(entry.name, entry);
- }
- for (const entry of cwdEntries) {
- map.set(entry.name, entry);
- }
- return [...map.values()].sort((a, b) => a.name.localeCompare(b.name));
+ const map = new Map<string, SkillEntry>();
+ for (const entry of homeEntries) {
+ map.set(entry.name, entry);
+ }
+ for (const entry of cwdEntries) {
+ map.set(entry.name, entry);
+ }
+ return [...map.values()].sort((a, b) => a.name.localeCompare(b.name));
}
/**
@@ -70,18 +70,18 @@ export function mergeCatalog(
* Lists all skills by name; appends summary only for skills with valid metadata.
*/
export function renderDescription(catalog: readonly SkillEntry[]): string {
- if (catalog.length === 0) {
- return "Load a skill by name. No skills are currently available.";
- }
- const lines = ["Load a skill by name. Available skills:"];
- for (const entry of catalog) {
- if (entry.summary !== undefined) {
- lines.push(`- ${entry.name}: ${entry.summary}`);
- } else {
- lines.push(`- ${entry.name}`);
- }
- }
- return lines.join("\n");
+ if (catalog.length === 0) {
+ return "Load a skill by name. No skills are currently available.";
+ }
+ const lines = ["Load a skill by name. Available skills:"];
+ for (const entry of catalog) {
+ if (entry.summary !== undefined) {
+ lines.push(`- ${entry.name}: ${entry.summary}`);
+ } else {
+ lines.push(`- ${entry.name}`);
+ }
+ }
+ return lines.join("\n");
}
/**
@@ -89,16 +89,16 @@ export function renderDescription(catalog: readonly SkillEntry[]): string {
* Returns true if the name is safe, false if it contains `/`, `\`, `..`, or is empty.
*/
export function isValidSkillName(name: unknown): name is string {
- if (typeof name !== "string" || name.length === 0) {
- return false;
- }
- if (name.includes("/") || name.includes("\\")) {
- return false;
- }
- if (name.includes("..")) {
- return false;
- }
- return true;
+ if (typeof name !== "string" || name.length === 0) {
+ return false;
+ }
+ if (name.includes("/") || name.includes("\\")) {
+ return false;
+ }
+ if (name.includes("..")) {
+ return false;
+ }
+ return true;
}
/**
@@ -106,6 +106,6 @@ export function isValidSkillName(name: unknown): name is string {
* Prefix check — catches `..` traversal and absolute paths outside base.
*/
export function isPathWithinDir(resolvedPath: string, base: string): boolean {
- const normalizedBase = base.endsWith("/") ? base : `${base}/`;
- return resolvedPath === base || resolvedPath.startsWith(normalizedBase);
+ const normalizedBase = base.endsWith("/") ? base : `${base}/`;
+ return resolvedPath === base || resolvedPath.startsWith(normalizedBase);
}