@hasna/skills 0.1.44 → 0.1.46

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/bin/mcp.js CHANGED
@@ -21797,7 +21797,7 @@ class StdioServerTransport {
21797
21797
  // package.json
21798
21798
  var package_default = {
21799
21799
  name: "@hasna/skills",
21800
- version: "0.1.44",
21800
+ version: "0.1.46",
21801
21801
  description: "Skills library for AI coding agents",
21802
21802
  type: "module",
21803
21803
  bin: {
@@ -21808,6 +21808,10 @@ var package_default = {
21808
21808
  ".": {
21809
21809
  import: "./dist/index.js",
21810
21810
  types: "./dist/index.d.ts"
21811
+ },
21812
+ "./storage": {
21813
+ import: "./dist/storage.js",
21814
+ types: "./dist/storage.d.ts"
21811
21815
  }
21812
21816
  },
21813
21817
  files: [
@@ -21828,7 +21832,7 @@ var package_default = {
21828
21832
  types: "./dist/index.d.ts",
21829
21833
  scripts: {
21830
21834
  clean: "rm -rf bin/ dist/",
21831
- build: "bun run clean && bun build ./src/cli/index.tsx --outdir ./bin --target bun --external ink --external react --external chalk && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/index.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
21835
+ build: "bun run clean && bun build ./src/cli/index.tsx --outdir ./bin --target bun && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/index.ts ./src/storage.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
21832
21836
  test: "bun test",
21833
21837
  dev: "bun run ./src/cli/index.tsx",
21834
21838
  "dev:watch": "bun --watch run ./src/cli/index.tsx",
@@ -21858,9 +21862,11 @@ var package_default = {
21858
21862
  devDependencies: {
21859
21863
  "@types/bun": "latest",
21860
21864
  "@types/react": "^18.2.0",
21865
+ "react-devtools-core": "^7.0.1",
21861
21866
  typescript: "^5"
21862
21867
  },
21863
21868
  dependencies: {
21869
+ "@hasna/events": "^0.1.3",
21864
21870
  "@modelcontextprotocol/sdk": "^1.26.0",
21865
21871
  chalk: "^5.3.0",
21866
21872
  commander: "^12.1.0",
@@ -30115,12 +30121,47 @@ function ensurePortableSkillFiles(skillPath, manifest) {
30115
30121
  writeFileSync2(join3(skillPath, "skill.json"), renderSkillJson(next));
30116
30122
  if (!existsSync3(join3(skillPath, "AGENTS.md")))
30117
30123
  writeFileSync2(join3(skillPath, "AGENTS.md"), renderAgentsMd(next));
30118
- if (!existsSync3(join3(skillPath, "package.json")))
30119
- writeFileSync2(join3(skillPath, "package.json"), renderPackageJson(next));
30124
+ ensurePackageJson(skillPath, next);
30120
30125
  if (!existsSync3(join3(skillPath, "tsconfig.json")))
30121
30126
  writeFileSync2(join3(skillPath, "tsconfig.json"), renderTsconfig());
30122
30127
  return readPortableSkillManifest(skillPath, next.name);
30123
30128
  }
30129
+ function ensurePackageJson(skillPath, manifest) {
30130
+ const pkgPath = join3(skillPath, "package.json");
30131
+ const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
30132
+ const commandName = normalizePortableSkillName(first.name || manifest.name);
30133
+ const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
30134
+ if (!existsSync3(pkgPath)) {
30135
+ writeFileSync2(pkgPath, renderPackageJson(manifest));
30136
+ return;
30137
+ }
30138
+ const existing = readJsonObject(pkgPath);
30139
+ const bin = {};
30140
+ if (isRecord(existing.bin)) {
30141
+ for (const [name, value] of Object.entries(existing.bin)) {
30142
+ if (typeof value === "string" && value.trim())
30143
+ bin[normalizePortableSkillName(name)] = value.replace(/^\.\//, "");
30144
+ }
30145
+ } else {
30146
+ const binEntry = stringValue(existing.bin);
30147
+ if (binEntry)
30148
+ bin[manifest.name] = binEntry.replace(/^\.\//, "");
30149
+ }
30150
+ bin[commandName] = entry;
30151
+ const scripts = isRecord(existing.scripts) ? { ...existing.scripts } : {};
30152
+ if (!stringValue(scripts.dev))
30153
+ scripts.dev = `bun run ${entry}`;
30154
+ writeFileSync2(pkgPath, `${JSON.stringify({
30155
+ ...existing,
30156
+ name: manifest.name,
30157
+ version: manifest.version,
30158
+ description: manifest.description,
30159
+ type: stringValue(existing.type) ?? "module",
30160
+ bin,
30161
+ scripts
30162
+ }, null, 2)}
30163
+ `);
30164
+ }
30124
30165
  function copySkillDirectory(source, destination) {
30125
30166
  mkdirSync2(destination, { recursive: true });
30126
30167
  cpSync(source, destination, {
@@ -33297,6 +33338,46 @@ var toolContracts = [
33297
33338
  inputSchema: objectSchema(),
33298
33339
  outputSchema: objectSchema({}, [], "Setup summary.", true)
33299
33340
  },
33341
+ {
33342
+ name: "storage_status",
33343
+ title: "Storage Status",
33344
+ description: "Show local-first storage paths and optional repo-owned Postgres/S3 readiness.",
33345
+ params: ["directory?"],
33346
+ category: "storage",
33347
+ sideEffects: "none",
33348
+ stable: true,
33349
+ inputSchema: objectSchema({ directory: stringSchema("Project directory.") }),
33350
+ outputSchema: objectSchema({
33351
+ package: stringSchema("Package name."),
33352
+ mode: { type: "string", enum: ["local", "remote", "hybrid"] },
33353
+ local: objectSchema({}, [], "Local storage paths.", true),
33354
+ remote: objectSchema({}, [], "Remote storage readiness.", true)
33355
+ }, ["package", "mode", "local", "remote"])
33356
+ },
33357
+ {
33358
+ name: "storage_sync_plan",
33359
+ title: "Storage Sync Plan",
33360
+ description: "Plan .skills snapshot sync for optional Postgres/S3 storage without network access.",
33361
+ params: ["directory?", "includeSchemaSql?"],
33362
+ category: "storage",
33363
+ sideEffects: "none",
33364
+ stable: true,
33365
+ inputSchema: objectSchema({
33366
+ directory: stringSchema("Project directory."),
33367
+ includeSchemaSql: { type: "boolean", default: false }
33368
+ }),
33369
+ outputSchema: objectSchema({
33370
+ package: stringSchema("Package name."),
33371
+ noNetwork: { type: "boolean", const: true },
33372
+ mode: { type: "string", enum: ["local", "remote", "hybrid"] },
33373
+ databaseConfigured: { type: "boolean" },
33374
+ s3Configured: { type: "boolean" },
33375
+ snapshotFileCount: { type: "number" },
33376
+ s3ObjectCount: { type: "number" },
33377
+ env: objectSchema({}, [], "Storage env var names.", true),
33378
+ schemaSql: stringSchema("Optional Postgres schema SQL.")
33379
+ }, ["package", "noNetwork", "mode", "databaseConfigured", "s3Configured"])
33380
+ },
33300
33381
  {
33301
33382
  name: "schedule_skill",
33302
33383
  title: "Schedule Skill",
@@ -34923,6 +35004,266 @@ function registerScheduleTools(server) {
34923
35004
  });
34924
35005
  }
34925
35006
 
35007
+ // src/lib/native-storage.ts
35008
+ init_config();
35009
+ import { createHash as createHash2, createHmac } from "crypto";
35010
+ import {
35011
+ existsSync as existsSync13,
35012
+ mkdirSync as mkdirSync8,
35013
+ readFileSync as readFileSync11,
35014
+ readdirSync as readdirSync6,
35015
+ statSync as statSync5,
35016
+ writeFileSync as writeFileSync7
35017
+ } from "fs";
35018
+ import { dirname as dirname5, join as join13, normalize as normalize3, relative as relative3, sep } from "path";
35019
+ var SKILLS_STORAGE_TABLES = [
35020
+ "skills_sync_records",
35021
+ "skills_sync_cursors"
35022
+ ];
35023
+ var SKILLS_NATIVE_STORAGE_ENV = {
35024
+ mode: "HASNA_SKILLS_STORAGE_MODE",
35025
+ databaseUrl: "HASNA_SKILLS_DATABASE_URL",
35026
+ databaseSsl: "HASNA_SKILLS_DATABASE_SSL",
35027
+ databaseSchema: "HASNA_SKILLS_DATABASE_SCHEMA",
35028
+ s3Bucket: "HASNA_SKILLS_S3_BUCKET",
35029
+ s3Prefix: "HASNA_SKILLS_S3_PREFIX",
35030
+ awsRegion: "HASNA_SKILLS_AWS_REGION",
35031
+ s3Endpoint: "HASNA_SKILLS_S3_ENDPOINT",
35032
+ s3ForcePathStyle: "HASNA_SKILLS_S3_FORCE_PATH_STYLE",
35033
+ s3AccessKeyId: "HASNA_SKILLS_S3_ACCESS_KEY_ID",
35034
+ s3SecretAccessKey: "HASNA_SKILLS_S3_SECRET_ACCESS_KEY",
35035
+ s3SessionToken: "HASNA_SKILLS_S3_SESSION_TOKEN",
35036
+ syncBatchSize: "HASNA_SKILLS_SYNC_BATCH_SIZE",
35037
+ dryRun: "HASNA_SKILLS_SYNC_DRY_RUN"
35038
+ };
35039
+ var SKILLS_NATIVE_STORAGE_FALLBACK_ENV = {
35040
+ mode: "SKILLS_STORAGE_MODE",
35041
+ databaseUrl: "SKILLS_DATABASE_URL",
35042
+ databaseSsl: "SKILLS_DATABASE_SSL",
35043
+ databaseSchema: "SKILLS_DATABASE_SCHEMA",
35044
+ s3Bucket: "SKILLS_S3_BUCKET",
35045
+ s3Prefix: "SKILLS_S3_PREFIX",
35046
+ awsRegion: "SKILLS_AWS_REGION",
35047
+ s3Endpoint: "SKILLS_S3_ENDPOINT",
35048
+ s3ForcePathStyle: "SKILLS_S3_FORCE_PATH_STYLE",
35049
+ s3AccessKeyId: "SKILLS_S3_ACCESS_KEY_ID",
35050
+ s3SecretAccessKey: "SKILLS_S3_SECRET_ACCESS_KEY",
35051
+ s3SessionToken: "SKILLS_S3_SESSION_TOKEN",
35052
+ syncBatchSize: "SKILLS_SYNC_BATCH_SIZE",
35053
+ dryRun: "SKILLS_SYNC_DRY_RUN"
35054
+ };
35055
+ function resolveSkillsNativeStorageConfig(env = process.env) {
35056
+ const mode = getSkillsStorageMode(env);
35057
+ return {
35058
+ mode,
35059
+ databaseUrl: getSkillsStorageDatabaseUrl(env),
35060
+ databaseSsl: parseBoolean(readStorageEnv(env, "databaseSsl").value),
35061
+ databaseSchema: readStorageEnv(env, "databaseSchema").value,
35062
+ s3Bucket: readStorageEnv(env, "s3Bucket").value,
35063
+ s3Prefix: readStorageEnv(env, "s3Prefix").value,
35064
+ awsRegion: readStorageEnv(env, "awsRegion").value ?? "us-east-1",
35065
+ s3Endpoint: readStorageEnv(env, "s3Endpoint").value,
35066
+ s3ForcePathStyle: parseBoolean(readStorageEnv(env, "s3ForcePathStyle").value) ?? false,
35067
+ syncBatchSize: parsePositiveInteger(readStorageEnv(env, "syncBatchSize").value) ?? 500,
35068
+ dryRun: parseBoolean(readStorageEnv(env, "dryRun").value) ?? true
35069
+ };
35070
+ }
35071
+ function resolveStorageConfig(env = process.env) {
35072
+ return resolveSkillsNativeStorageConfig(env);
35073
+ }
35074
+ function getSkillsStorageMode(env = process.env) {
35075
+ return parseMode(readStorageEnv(env, "mode").value);
35076
+ }
35077
+ function getSkillsStorageDatabaseUrl(env = process.env) {
35078
+ return readStorageEnv(env, "databaseUrl").value;
35079
+ }
35080
+ function getSkillsNativeStorageStatus(options = {}) {
35081
+ const env = options.env ?? process.env;
35082
+ const config2 = resolveSkillsNativeStorageConfig(env);
35083
+ const modeEnv = readStorageEnv(env, "mode");
35084
+ const databaseEnv = readStorageEnv(env, "databaseUrl");
35085
+ const s3BucketEnv = readStorageEnv(env, "s3Bucket");
35086
+ const targetDir = options.targetDir ?? process.cwd();
35087
+ return {
35088
+ package: "open-skills",
35089
+ mode: config2.mode,
35090
+ tables: [...SKILLS_STORAGE_TABLES],
35091
+ env: {
35092
+ mode: SKILLS_NATIVE_STORAGE_ENV.mode,
35093
+ databaseUrl: SKILLS_NATIVE_STORAGE_ENV.databaseUrl,
35094
+ s3Bucket: SKILLS_NATIVE_STORAGE_ENV.s3Bucket
35095
+ },
35096
+ local: {
35097
+ dataDir: getDataDir(),
35098
+ projectStateDir: getProjectStateDir(targetDir),
35099
+ feedbackDbPath: join13(getDataDir(), "skills.db")
35100
+ },
35101
+ remote: {
35102
+ databaseConfigured: Boolean(config2.databaseUrl),
35103
+ s3Configured: Boolean(config2.s3Bucket),
35104
+ databaseEnv: SKILLS_NATIVE_STORAGE_ENV.databaseUrl,
35105
+ s3BucketEnv: SKILLS_NATIVE_STORAGE_ENV.s3Bucket,
35106
+ activeModeEnv: modeEnv.name,
35107
+ activeDatabaseEnv: databaseEnv.name,
35108
+ activeS3BucketEnv: s3BucketEnv.name,
35109
+ region: config2.awsRegion ?? "us-east-1",
35110
+ dryRun: config2.dryRun
35111
+ }
35112
+ };
35113
+ }
35114
+ function getStorageStatus(options = {}) {
35115
+ return getSkillsNativeStorageStatus(options);
35116
+ }
35117
+ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
35118
+ const projectStateDir = getProjectStateDir(targetDir);
35119
+ const files = [];
35120
+ if (existsSync13(projectStateDir)) {
35121
+ for (const filePath of walkFiles2(projectStateDir)) {
35122
+ const bytes = readFileSync11(filePath);
35123
+ const relativePath = toPosix(relative3(targetDir, filePath));
35124
+ files.push({
35125
+ path: relativePath,
35126
+ sizeBytes: bytes.byteLength,
35127
+ sha256: createHash2("sha256").update(bytes).digest("hex"),
35128
+ ...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
35129
+ });
35130
+ }
35131
+ }
35132
+ return {
35133
+ schemaVersion: 1,
35134
+ exportedAt: new Date().toISOString(),
35135
+ files: files.sort((a, b) => a.path.localeCompare(b.path))
35136
+ };
35137
+ }
35138
+ var skillsPostgresSyncSchemaSql = `
35139
+ CREATE TABLE IF NOT EXISTS skills_sync_records (
35140
+ scope TEXT NOT NULL,
35141
+ kind TEXT NOT NULL,
35142
+ id TEXT NOT NULL,
35143
+ updated_at TIMESTAMPTZ NOT NULL,
35144
+ deleted_at TIMESTAMPTZ,
35145
+ source TEXT,
35146
+ payload JSONB NOT NULL,
35147
+ PRIMARY KEY (scope, kind, id)
35148
+ );
35149
+
35150
+ CREATE INDEX IF NOT EXISTS skills_sync_records_updated_at_idx
35151
+ ON skills_sync_records (updated_at);
35152
+
35153
+ CREATE TABLE IF NOT EXISTS skills_sync_cursors (
35154
+ scope TEXT NOT NULL,
35155
+ cursor_name TEXT NOT NULL,
35156
+ value TEXT NOT NULL,
35157
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
35158
+ PRIMARY KEY (scope, cursor_name)
35159
+ );
35160
+ `.trim();
35161
+ function planSkillsS3SnapshotUpload(snapshot, options = {}) {
35162
+ const prefix = normalizeS3Prefix(options.prefix);
35163
+ return snapshot.files.map((file2) => ({
35164
+ path: file2.path,
35165
+ key: [prefix, file2.path.replace(/^\.?\//, "")].filter(Boolean).join("/"),
35166
+ sizeBytes: file2.sizeBytes,
35167
+ sha256: file2.sha256
35168
+ }));
35169
+ }
35170
+ function parseMode(value) {
35171
+ const normalized = value?.trim().toLowerCase();
35172
+ if (normalized === "remote" || normalized === "hybrid")
35173
+ return normalized;
35174
+ return "local";
35175
+ }
35176
+ function readStorageEnv(env, key) {
35177
+ const primaryName = SKILLS_NATIVE_STORAGE_ENV[key];
35178
+ const primaryValue = cleanOptional(env[primaryName]);
35179
+ if (primaryValue !== undefined)
35180
+ return { name: primaryName, value: primaryValue };
35181
+ const fallbackName = SKILLS_NATIVE_STORAGE_FALLBACK_ENV[key];
35182
+ const fallbackValue = cleanOptional(env[fallbackName]);
35183
+ if (fallbackValue !== undefined)
35184
+ return { name: fallbackName, value: fallbackValue };
35185
+ return { name: primaryName };
35186
+ }
35187
+ function cleanOptional(value) {
35188
+ const cleaned = value?.trim();
35189
+ return cleaned ? cleaned : undefined;
35190
+ }
35191
+ function parseBoolean(value) {
35192
+ if (value === undefined)
35193
+ return;
35194
+ const normalized = value.trim().toLowerCase();
35195
+ if (["1", "true", "yes", "on"].includes(normalized))
35196
+ return true;
35197
+ if (["0", "false", "no", "off"].includes(normalized))
35198
+ return false;
35199
+ return;
35200
+ }
35201
+ function parsePositiveInteger(value) {
35202
+ if (!value)
35203
+ return;
35204
+ const parsed = Number.parseInt(value, 10);
35205
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
35206
+ }
35207
+ function walkFiles2(dir) {
35208
+ const files = [];
35209
+ for (const entry of readdirSync6(dir)) {
35210
+ const full = join13(dir, entry);
35211
+ const stats = statSync5(full);
35212
+ if (stats.isDirectory())
35213
+ files.push(...walkFiles2(full));
35214
+ else
35215
+ files.push(full);
35216
+ }
35217
+ return files;
35218
+ }
35219
+ function normalizeS3Prefix(prefix) {
35220
+ return (prefix ?? "").trim().replace(/^\/+|\/+$/g, "");
35221
+ }
35222
+ function toPosix(path) {
35223
+ return path.split(/[\\/]+/).join("/");
35224
+ }
35225
+
35226
+ // src/mcp/storage-tools.ts
35227
+ function registerStorageTools(server) {
35228
+ server.registerTool("storage_status", {
35229
+ title: "Storage Status",
35230
+ description: "Show local-first storage paths and optional repo-owned Postgres/S3 readiness.",
35231
+ inputSchema: {
35232
+ directory: exports_external.string().optional()
35233
+ }
35234
+ }, async ({ directory }) => {
35235
+ return mcpJson(getStorageStatus({ targetDir: directory || process.cwd() }), true);
35236
+ });
35237
+ server.registerTool("storage_sync_plan", {
35238
+ title: "Storage Sync Plan",
35239
+ description: "Plan .skills snapshot sync for optional Postgres/S3 storage without network access.",
35240
+ inputSchema: {
35241
+ directory: exports_external.string().optional(),
35242
+ includeSchemaSql: exports_external.boolean().optional()
35243
+ }
35244
+ }, async ({ directory, includeSchemaSql }) => {
35245
+ const targetDir = directory || process.cwd();
35246
+ const config2 = resolveStorageConfig();
35247
+ const snapshot = exportSkillsLocalSnapshot(targetDir, { includeFileContents: false });
35248
+ const s3Plan = config2.s3Bucket ? planSkillsS3SnapshotUpload(snapshot, { prefix: config2.s3Prefix }) : [];
35249
+ return mcpJson({
35250
+ package: "open-skills",
35251
+ noNetwork: true,
35252
+ mode: config2.mode,
35253
+ databaseConfigured: Boolean(config2.databaseUrl),
35254
+ s3Configured: Boolean(config2.s3Bucket),
35255
+ snapshotFileCount: snapshot.files.length,
35256
+ s3ObjectCount: s3Plan.length,
35257
+ env: {
35258
+ mode: SKILLS_NATIVE_STORAGE_ENV.mode,
35259
+ databaseUrl: SKILLS_NATIVE_STORAGE_ENV.databaseUrl,
35260
+ s3Bucket: SKILLS_NATIVE_STORAGE_ENV.s3Bucket
35261
+ },
35262
+ ...includeSchemaSql ? { schemaSql: skillsPostgresSyncSchemaSql } : {}
35263
+ }, true);
35264
+ });
35265
+ }
35266
+
34926
35267
  // src/mcp/server.ts
34927
35268
  function buildServer() {
34928
35269
  const server = new McpServer({
@@ -34932,6 +35273,7 @@ function buildServer() {
34932
35273
  registerDiscoveryTools(server);
34933
35274
  registerOperationTools(server);
34934
35275
  registerScheduleTools(server);
35276
+ registerStorageTools(server);
34935
35277
  registerResourceMetaTools(server);
34936
35278
  return server;
34937
35279
  }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerStorage(parent: Command): void;
package/dist/index.d.ts CHANGED
@@ -25,5 +25,6 @@ export { SKILLS_CLI_MCP_PARITY, findSkillsParityForCliCommand, findSkillsParityF
25
25
  export { createRegistrySyncArtifact, writeRegistrySyncArtifact, type RegistrySyncArtifact, type RegistrySyncOptions, type RegistrySyncSkill, } from "./lib/registry-sync.js";
26
26
  export { MCP_CONTRACT_SCHEMA_VERSION, createMcpContractManifest, createSkillMcpMetadata, describeMcpToolContracts, getMcpResourceContracts, getMcpToolDescriptions, listMcpToolContracts, summarizeMcpToolContract, type DescribedMcpToolContract, type JsonSchemaObject, type McpContractManifest, type McpResourceContract, type McpToolCategory, type McpToolContract, type McpToolSideEffect, type SkillMcpMetadata, type SkillMcpSchemaContract, type UnknownMcpToolContract, } from "./lib/mcp-contracts.js";
27
27
  export { getFeedbackDbPath, saveFeedback, type FeedbackCategory, type FeedbackInput, type FeedbackResult, } from "./lib/feedback.js";
28
+ export { SKILLS_NATIVE_STORAGE_ENV, SKILLS_NATIVE_STORAGE_FALLBACK_ENV, SKILLS_STORAGE_ENV, SKILLS_STORAGE_FALLBACK_ENV, SKILLS_STORAGE_TABLES, STORAGE_TABLES, SkillsPostgresSyncStore, SkillsS3ObjectStore, buildSkillsS3ObjectUrl, createSkillsPostgresSyncStore, createSkillsS3ObjectStore, createSkillsSnapshotSyncRecord, exportSkillsLocalSnapshot, getSkillsNativeStorageStatus, getSkillsStorageDatabaseEnv, getSkillsStorageDatabaseUrl, getSkillsStorageMode, getSkillsStorageStatus, getStorageDatabaseEnv, getStorageDatabaseUrl, getStorageMode, getStorageStatus, importSkillsLocalSnapshot, planSkillsS3SnapshotUpload, resolveSkillsNativeStorageConfig, resolveStorageConfig, signSkillsAwsV4Request, skillsPostgresSyncSchemaSql, uploadSkillsSnapshotFilesToS3, type AwsCredentials, type SignSkillsAwsV4RequestOptions, type SkillsFetch, type SkillsLocalSnapshot, type SkillsNativeStorageConfig, type SkillsNativeStorageStatus, type SkillsPostgresQueryClient, type SkillsS3ObjectStoreOptions, type SkillsS3PutObjectOptions, type SkillsS3SnapshotPlanEntry, type SkillsS3StoredObject, type SkillsSnapshotFile, type SkillsStorageMode, type SkillsStorageTable, type SkillsSyncRecord, } from "./lib/native-storage.js";
28
29
  export { SKILL_ALIASES, normalizeSkillSlug, resolveSkillAlias, type SkillAlias, } from "./lib/skill-aliases.js";
29
30
  export type { SkillResponse, SkillDetailResponse, CategoryResponse, TagResponse, InstallResponse, RemoveResponse, VersionResponse, ExportResponse, ImportResponse, SearchResponse, CategoryInstallResponse, ErrorResponse, } from "./types/api.js";