/** * Shared extension utilities. * * Cross-cutting utilities used by multiple extension types. * Promoted from skills-specific modules to avoid cross-feature dependencies. * * @experimental This API is unstable and may change without notice. * @packageDocumentation */ import type { PlatformError } from "effect/PlatformError"; import * as FileSystem from "effect/FileSystem"; import * as Path from "effect/Path"; import * as Effect from "effect/Effect"; import { type ExtensionName } from "./common.js"; /** * Sanitizes an extension name into a safe on-disk directory name. * * Transformation pipeline: * 1. Convert to lowercase * 2. Replace non-alphanumeric characters (except `.` and `_`) with hyphens * 3. Strip leading dots and hyphens * 4. Truncate to 255 characters, then strip trailing dots and hyphens * 5. Fall back to `"unnamed-skill"` if empty * 6. Preserve canonical names; otherwise append a deterministic discriminator */ export declare const sanitizeName: (name: string) => string; /** * Converts a human-authored label into a valid AXM extension name. */ export declare const normalizeExtensionName: (name: string) => ExtensionName; export declare const validatePathSafety: (path: Path.Path, baseDir: string, targetPath: string) => import("../app-error/app-error.ts").AppError | Effect.Effect; /** * Options for {@link copyExtensionDirectory}. */ export type CopyExtensionDirectoryOptions = { /** * When true, omit entries that should not appear in a fanned-out agent * artifact: `README.md`, `metadata.json`, and `_`-prefixed names (`.git` is * always omitted). * * Defaults to `false` — a faithful copy of the source, matching what * `publish` packages into the archive. Canonical materialization must use * the faithful copy so realigning a lockfile does not strip authored files * (e.g. `README.md`) that the published package contains. */ readonly forAgentArtifact?: boolean; }; export type CopyExtensionDirectoryFailureDetails = { readonly sourcePath: string; readonly targetPath: string; readonly subject?: string; readonly sourceExists?: boolean; }; export declare const formatCopyExtensionDirectoryFailure: ({ sourcePath, targetPath, subject, sourceExists, }: CopyExtensionDirectoryFailureDetails) => string; /** * Recursively copies an extension directory from `src` to `dest`. * * By default this is a faithful copy of every entry except `.git`, used to * materialize the canonical extension store from a package archive or local * source. Pass `{ forAgentArtifact: true }` to also omit non-artifact entries * when fanning the canonical copy out to an agent directory (see * {@link CopyExtensionDirectoryOptions}). * * Symlinks are dereferenced (file content is copied, not the link). * Directory entries are copied concurrently. */ export declare const copyExtensionDirectory: (src: string, dest: string, options?: CopyExtensionDirectoryOptions) => Effect.Effect; //# sourceMappingURL=utils.d.ts.map