@hasna/skills 0.1.72 → 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.
package/bin/mcp.js CHANGED
@@ -6679,92 +6679,77 @@ var init_retired_settings = __esm(() => {
6679
6679
  };
6680
6680
  });
6681
6681
 
6682
- // ../../node_modules/.bun/@hasna+paths@0.1.0/node_modules/@hasna/paths/dist/index.js
6682
+ // src/lib/app-home.ts
6683
+ import { existsSync } from "fs";
6683
6684
  import { homedir } from "os";
6684
- import { join } from "path";
6685
- function assertApp(app) {
6685
+ import { join, resolve } from "path";
6686
+ import { homedir as pathsResolverHomedir } from "os";
6687
+ import { join as pathsResolverJoin } from "path";
6688
+ function pathsResolverAssertApp(app) {
6686
6689
  if (typeof app !== "string" || app.length === 0) {
6687
6690
  throw new TypeError("paths: app must be a non-empty string");
6688
6691
  }
6689
- if (!APP_SLUG_RE.test(app)) {
6692
+ if (!PATHS_RESOLVER_APP_SLUG_RE.test(app)) {
6690
6693
  throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
6691
6694
  }
6692
6695
  }
6693
- function envOf(options) {
6694
- return options.env ?? process.env;
6695
- }
6696
- function envValue(options, kind) {
6697
- const value = envOf(options)[KIND_ENV[kind]];
6698
- return typeof value === "string" && value.length > 0 ? value : undefined;
6699
- }
6700
- function isMacOS(platform) {
6701
- return platform === "darwin";
6696
+ function pathsResolverAssertKind(kind) {
6697
+ if (!Object.keys(PATHS_RESOLVER_KIND_ENV).includes(kind)) {
6698
+ throw new TypeError(`paths: invalid path kind "${kind}" \u2014 expected one of ${Object.keys(PATHS_RESOLVER_KIND_ENV).join(", ")}`);
6699
+ }
6702
6700
  }
6703
- function baseDir(kind, options) {
6704
- const override = envValue(options, kind);
6705
- if (override)
6701
+ function pathsResolverBaseDir(kind, options) {
6702
+ pathsResolverAssertKind(kind);
6703
+ const env = options.env ?? process.env;
6704
+ const override = env[PATHS_RESOLVER_KIND_ENV[kind]];
6705
+ if (typeof override === "string" && override.length > 0)
6706
6706
  return override;
6707
- const home = options.home ?? homedir();
6707
+ const home = options.home ?? pathsResolverHomedir();
6708
6708
  const platform = options.platform ?? process.platform;
6709
- if (isMacOS(platform)) {
6709
+ if (platform === "darwin") {
6710
6710
  switch (kind) {
6711
6711
  case "config":
6712
6712
  case "data":
6713
- return join(home, "Library", "Application Support", "Hasna");
6713
+ return pathsResolverJoin(home, "Library", "Application Support", "Hasna");
6714
6714
  case "cache":
6715
- return join(home, "Library", "Caches", "Hasna");
6715
+ return pathsResolverJoin(home, "Library", "Caches", "Hasna");
6716
6716
  case "state":
6717
- return join(home, "Library", "Logs", "Hasna");
6717
+ return pathsResolverJoin(home, "Library", "Logs", "Hasna");
6718
6718
  }
6719
6719
  }
6720
6720
  switch (kind) {
6721
6721
  case "config":
6722
- return join(home, ".config", "hasna");
6722
+ return pathsResolverJoin(home, ".config", "hasna");
6723
6723
  case "data":
6724
- return join(home, ".local", "share", "hasna");
6724
+ return pathsResolverJoin(home, ".local", "share", "hasna");
6725
6725
  case "state":
6726
- return join(home, ".local", "state", "hasna");
6726
+ return pathsResolverJoin(home, ".local", "state", "hasna");
6727
6727
  case "cache":
6728
- return join(home, ".cache", "hasna");
6728
+ return pathsResolverJoin(home, ".cache", "hasna");
6729
6729
  }
6730
6730
  }
6731
- function resolvePath(kind, options) {
6732
- assertApp(options.app);
6733
- const appSegment = options.internal === true ? join("internal", options.app) : options.app;
6734
- return join(baseDir(kind, options), appSegment);
6731
+ function pathsResolverResolve(kind, options) {
6732
+ pathsResolverAssertApp(options.app);
6733
+ const appSegment = options.internal === true ? pathsResolverJoin("internal", options.app) : options.app;
6734
+ return pathsResolverJoin(pathsResolverBaseDir(kind, options), appSegment);
6735
6735
  }
6736
6736
  function dataDir(options) {
6737
- return resolvePath("data", options);
6737
+ return pathsResolverResolve("data", options);
6738
6738
  }
6739
- var KIND_ENV, APP_SLUG_RE;
6740
- var init_dist = __esm(() => {
6741
- KIND_ENV = {
6742
- config: "HASNA_CONFIG_HOME",
6743
- data: "HASNA_DATA_HOME",
6744
- state: "HASNA_STATE_HOME",
6745
- cache: "HASNA_CACHE_HOME"
6746
- };
6747
- APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
6748
- });
6749
-
6750
- // src/lib/app-home.ts
6751
- import { existsSync } from "fs";
6752
- import { homedir as homedir2 } from "os";
6753
- import { join as join2, resolve } from "path";
6754
6739
  function effectiveHome() {
6755
- return process.env["HOME"] || process.env["USERPROFILE"] || homedir2() || "/tmp";
6740
+ return process.env["HOME"] || process.env["USERPROFILE"] || homedir() || "/tmp";
6756
6741
  }
6757
6742
  function legacyDataRoot() {
6758
- return join2(effectiveHome(), ".hasna", "skills");
6743
+ return join(effectiveHome(), ".hasna", "skills");
6759
6744
  }
6760
- function resolverDataRoot(home = effectiveHome()) {
6761
- return dataDir({ app: "skills", home });
6745
+ function resolverDataRoot(home = effectiveHome(), env) {
6746
+ return dataDir({ app: "skills", home, env });
6762
6747
  }
6763
6748
  function adoptResolverDataRoot(resolved, env = process.env) {
6764
6749
  const dataOverride = env.HASNA_DATA_HOME;
6765
6750
  if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
6766
6751
  return true;
6767
- return existsSync(join2(resolved, DEFAULT_SQLITE_FILENAME)) || existsSync(join2(resolved, GLOBAL_CONFIG_FILENAME));
6752
+ return existsSync(join(resolved, DEFAULT_SQLITE_FILENAME)) || existsSync(join(resolved, GLOBAL_CONFIG_FILENAME));
6768
6753
  }
6769
6754
  function exactDataRoot() {
6770
6755
  for (const key of [DATA_DIR_ENV, HASNA_SKILLS_HOME_ENV, SKILLS_HOME_ENV]) {
@@ -6787,15 +6772,21 @@ function getDataRoot() {
6787
6772
  const resolved = resolverDataRoot();
6788
6773
  return adoptResolverDataRoot(resolved) ? resolve(resolved) : resolve(legacyDataRoot());
6789
6774
  }
6790
- var DATA_DIR_ENV = "HASNA_SKILLS_DIR", HASNA_SKILLS_HOME_ENV = "HASNA_SKILLS_HOME", SKILLS_HOME_ENV = "SKILLS_HOME", DEFAULT_SQLITE_FILENAME = "server.db", GLOBAL_CONFIG_FILENAME = "config.json";
6775
+ var PATHS_RESOLVER_KIND_ENV, PATHS_RESOLVER_APP_SLUG_RE, DATA_DIR_ENV = "HASNA_SKILLS_DIR", HASNA_SKILLS_HOME_ENV = "HASNA_SKILLS_HOME", SKILLS_HOME_ENV = "SKILLS_HOME", DEFAULT_SQLITE_FILENAME = "server.db", GLOBAL_CONFIG_FILENAME = "config.json";
6791
6776
  var init_app_home = __esm(() => {
6792
- init_dist();
6777
+ PATHS_RESOLVER_KIND_ENV = {
6778
+ config: "HASNA_CONFIG_HOME",
6779
+ data: "HASNA_DATA_HOME",
6780
+ state: "HASNA_STATE_HOME",
6781
+ cache: "HASNA_CACHE_HOME"
6782
+ };
6783
+ PATHS_RESOLVER_APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
6793
6784
  });
6794
6785
 
6795
6786
  // src/lib/config.ts
6796
6787
  import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync, copyFileSync, readdirSync, statSync } from "fs";
6797
- import { join as join3, dirname } from "path";
6798
- import { homedir as homedir3 } from "os";
6788
+ import { join as join2, dirname } from "path";
6789
+ import { homedir as homedir2 } from "os";
6799
6790
  function validKeys() {
6800
6791
  return [...Object.keys(ENUM_KEYS), ...STRING_KEYS];
6801
6792
  }
@@ -6807,8 +6798,8 @@ function mergeDirectoryContents(sourceDir, targetDir) {
6807
6798
  return;
6808
6799
  mkdirSync(targetDir, { recursive: true });
6809
6800
  for (const entry of readdirSync(sourceDir)) {
6810
- const sourcePath = join3(sourceDir, entry);
6811
- const targetPath = join3(targetDir, entry);
6801
+ const sourcePath = join2(sourceDir, entry);
6802
+ const targetPath = join2(targetDir, entry);
6812
6803
  try {
6813
6804
  const sourceStat = statSync(sourcePath);
6814
6805
  if (sourceStat.isDirectory()) {
@@ -6841,7 +6832,7 @@ function normalizeConfigValue(key, value) {
6841
6832
  return;
6842
6833
  }
6843
6834
  function isOwnerLayoutMigrated(appDir) {
6844
- return existsSync2(join3(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD));
6835
+ return existsSync2(join2(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD));
6845
6836
  }
6846
6837
  function getDataDir() {
6847
6838
  const root = getDataRoot();
@@ -6851,14 +6842,14 @@ function getDataDir() {
6851
6842
  if (hasOperatorOverride())
6852
6843
  return root;
6853
6844
  const home = effectiveHome();
6854
- const oldDir = join3(home, ".skills");
6855
- const oldConfigFile = join3(home, ".skillsrc");
6845
+ const oldDir = join2(home, ".skills");
6846
+ const oldConfigFile = join2(home, ".skillsrc");
6856
6847
  try {
6857
6848
  mergeDirectoryContents(oldDir, root);
6858
6849
  } catch {}
6859
- if (existsSync2(oldConfigFile) && !existsSync2(join3(root, "config.json"))) {
6850
+ if (existsSync2(oldConfigFile) && !existsSync2(join2(root, "config.json"))) {
6860
6851
  try {
6861
- copyFileSync(oldConfigFile, join3(root, "config.json"));
6852
+ copyFileSync(oldConfigFile, join2(root, "config.json"));
6862
6853
  } catch {}
6863
6854
  }
6864
6855
  return root;
@@ -6868,8 +6859,8 @@ function getDataDirReadOnly() {
6868
6859
  }
6869
6860
  function getConfigPathReadOnly(scope) {
6870
6861
  if (scope === "global")
6871
- return join3(getDataDirReadOnly(), "config.json");
6872
- return join3(process.cwd(), "skills.config.json");
6862
+ return join2(getDataDirReadOnly(), "config.json");
6863
+ return join2(process.cwd(), "skills.config.json");
6873
6864
  }
6874
6865
  function loadConfigReadOnly() {
6875
6866
  const canonicalConfigPath = getConfigPathReadOnly("global");
@@ -6885,13 +6876,13 @@ function loadConfigReadOnly() {
6885
6876
  return { ...globalConfig2, ...projectConfig };
6886
6877
  }
6887
6878
  function legacyConfigFilePath() {
6888
- return join3(process.env["HOME"] || process.env["USERPROFILE"] || homedir3(), ".skillsrc");
6879
+ return join2(process.env["HOME"] || process.env["USERPROFILE"] || homedir2(), ".skillsrc");
6889
6880
  }
6890
6881
  function getConfigPath(scope) {
6891
6882
  if (scope === "global") {
6892
- return join3(getDataDir(), "config.json");
6883
+ return join2(getDataDir(), "config.json");
6893
6884
  }
6894
- return join3(process.cwd(), "skills.config.json");
6885
+ return join2(process.cwd(), "skills.config.json");
6895
6886
  }
6896
6887
  function readConfigFile(path) {
6897
6888
  if (!existsSync2(path))
@@ -7015,16 +7006,16 @@ __export(exports_auth_store, {
7015
7006
  clearAuthConfig: () => clearAuthConfig
7016
7007
  });
7017
7008
  import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync6, unlinkSync } from "fs";
7018
- import { dirname as dirname5, join as join14 } from "path";
7019
- import { homedir as homedir5 } from "os";
7009
+ import { dirname as dirname5, join as join13 } from "path";
7010
+ import { homedir as homedir4 } from "os";
7020
7011
  function getAuthFilePath() {
7021
- return join14(getDataDir(), "auth.json");
7012
+ return join13(getDataDir(), "auth.json");
7022
7013
  }
7023
7014
  function getAuthFilePathReadOnly() {
7024
- return join14(getDataDirReadOnly(), "auth.json");
7015
+ return join13(getDataDirReadOnly(), "auth.json");
7025
7016
  }
7026
7017
  function legacyAuthFilePath() {
7027
- return join14(process.env["HOME"] || process.env["USERPROFILE"] || homedir5(), ".skills", "auth.json");
7018
+ return join13(process.env["HOME"] || process.env["USERPROFILE"] || homedir4(), ".skills", "auth.json");
7028
7019
  }
7029
7020
  function getAuthConfig() {
7030
7021
  if (cachedConfig !== undefined)
@@ -7356,12 +7347,30 @@ class RemoteSkillsClient {
7356
7347
  async downloadSkillBundle(slug) {
7357
7348
  return this.request(`/api/v1/skills/${encodeURIComponent(slug)}/bundle`, { method: "GET" });
7358
7349
  }
7359
- async getBundle(slug) {
7360
- const response = await this.request(`/api/v1/skills/${encodeURIComponent(slug)}/bundle`, { method: "GET" });
7350
+ async getBundle(slug, version2) {
7351
+ const path = version2 ? `/api/v1/skills/${encodeURIComponent(slug)}/versions/${encodeURIComponent(version2)}/bundle` : `/api/v1/skills/${encodeURIComponent(slug)}/bundle`;
7352
+ const response = await this.request(path, { method: "GET" });
7361
7353
  if (response.status === 404)
7362
7354
  return null;
7363
7355
  return response;
7364
7356
  }
7357
+ async listSkillVersions(slug) {
7358
+ const response = await this.requestNewRoute(`/api/v1/skills/${encodeURIComponent(slug)}/versions`, undefined, { domainNotFoundCodes: ["SKILL_NOT_FOUND"] });
7359
+ if (response.status === 404)
7360
+ return [];
7361
+ if (!response.ok)
7362
+ throw new Error(`versions request failed: ${response.status}`);
7363
+ const body = await response.json();
7364
+ return Array.isArray(body.versions) ? body.versions : [];
7365
+ }
7366
+ async getSkillVersion(slug, version2) {
7367
+ const response = await this.requestNewRoute(`/api/v1/skills/${encodeURIComponent(slug)}/versions/${encodeURIComponent(version2)}`, undefined, { domainNotFoundCodes: ["SKILL_NOT_FOUND", "SKILL_VERSION_NOT_FOUND"] });
7368
+ if (response.status === 404)
7369
+ return null;
7370
+ if (!response.ok)
7371
+ throw new Error(`version request failed: ${response.status}`);
7372
+ return await response.json();
7373
+ }
7365
7374
  async listPins() {
7366
7375
  const response = await this.requestNewRoute("/api/v1/pins");
7367
7376
  return normalizePinList(await response.json());
@@ -13052,7 +13061,7 @@ class StdioServerTransport {
13052
13061
  // package.json
13053
13062
  var package_default = {
13054
13063
  name: "@hasna/skills",
13055
- version: "0.1.72",
13064
+ version: "0.2.0",
13056
13065
  description: "Skills library for AI coding agents",
13057
13066
  type: "module",
13058
13067
  bin: {
@@ -13132,7 +13141,7 @@ var package_default = {
13132
13141
  author: "Hasna",
13133
13142
  license: "Apache-2.0",
13134
13143
  devDependencies: {
13135
- "@types/bun": "latest",
13144
+ "@types/bun": "1.3.14",
13136
13145
  "@types/node": "25.2.3",
13137
13146
  "@types/react": "^18.2.0",
13138
13147
  "bun-types": "1.3.14",
@@ -13144,7 +13153,6 @@ var package_default = {
13144
13153
  "@aws-sdk/client-ecs": "^3.1079.0",
13145
13154
  "@aws-sdk/client-s3": "^3.1079.0",
13146
13155
  "@hasna/events": "0.1.16",
13147
- "@hasna/paths": "0.1.0",
13148
13156
  "@modelcontextprotocol/sdk": "^1.26.0",
13149
13157
  chalk: "^5.3.0",
13150
13158
  commander: "^12.1.0",
@@ -20998,7 +21006,7 @@ var EMPTY_COMPLETION_RESULT = {
20998
21006
  // src/lib/registry.ts
20999
21007
  init_config();
21000
21008
  import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as readdirSync6 } from "fs";
21001
- import { join as join9 } from "path";
21009
+ import { join as join8 } from "path";
21002
21010
 
21003
21011
  // src/lib/portable-skills.ts
21004
21012
  init_config();
@@ -21013,7 +21021,7 @@ import {
21013
21021
  statSync as statSync6,
21014
21022
  writeFileSync as writeFileSync3
21015
21023
  } from "fs";
21016
- import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute2, join as join8, normalize as normalize2 } from "path";
21024
+ import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute2, join as join7, normalize as normalize2 } from "path";
21017
21025
 
21018
21026
  // src/lib/registry-data/development-tools.ts
21019
21027
  var DEVELOPMENT_TOOLS_SKILLS = [
@@ -21227,14 +21235,6 @@ var DEVELOPMENT_TOOLS_SKILLS = [
21227
21235
  category: "Development Tools",
21228
21236
  tags: ["storage", "backend", "postgresql", "sqlite", "two-backend", "oss-app"],
21229
21237
  kind: "instruction"
21230
- },
21231
- {
21232
- name: "session-inject-monitor",
21233
- displayName: "Session Inject Monitor",
21234
- description: "Set up a declarative monitor that injects a prompt into a live coding-agent session when a watched source (conversations, email, todos, knowledge, command output) has new content",
21235
- category: "Development Tools",
21236
- tags: ["monitor", "session", "injection", "automation", "wake"],
21237
- kind: "instruction"
21238
21238
  }
21239
21239
  ];
21240
21240
 
@@ -21734,7 +21734,7 @@ var SKILLS = [
21734
21734
 
21735
21735
  // src/lib/hosted-skill-set.ts
21736
21736
  import { existsSync as existsSync3, readFileSync as readFileSync2, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
21737
- import { join as join4 } from "path";
21737
+ import { join as join3 } from "path";
21738
21738
  var HOSTED_RUNTIMES = new Set(["hosted"]);
21739
21739
  var HOSTED_SOURCES = new Set(["remote", "private-hosted"]);
21740
21740
  function normalizeMarker(value) {
@@ -21747,7 +21747,7 @@ function isHostedMetadataPackage(pkg) {
21747
21747
  return HOSTED_RUNTIMES.has(normalizeMarker(skills.runtime)) || HOSTED_SOURCES.has(normalizeMarker(skills.source));
21748
21748
  }
21749
21749
  function isHostedMetadataSkillDir(skillDir) {
21750
- const pkgPath = join4(skillDir, "package.json");
21750
+ const pkgPath = join3(skillDir, "package.json");
21751
21751
  if (!existsSync3(pkgPath))
21752
21752
  return false;
21753
21753
  try {
@@ -21773,7 +21773,7 @@ var SINGLE_SOURCE_EXCLUSION = new RegExp(`^!skills/(${SLUG})/src$`);
21773
21773
 
21774
21774
  // src/lib/skill-validation.ts
21775
21775
  import { existsSync as existsSync4, lstatSync, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
21776
- import { isAbsolute, join as join5, normalize } from "path";
21776
+ import { isAbsolute, join as join4, normalize } from "path";
21777
21777
  var VALID_SKILL_KINDS = ["executable", "instruction"];
21778
21778
  var DOC_FILES = ["SKILL.md", "README.md", "CLAUDE.md"];
21779
21779
  var RESERVED_SKILL_ENTRIES = new Set([
@@ -21926,7 +21926,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21926
21926
  add(issues, "skill.name_invalid", `Skill name '${bareName}' must use lowercase letters, numbers, dots, underscores, or hyphens`);
21927
21927
  }
21928
21928
  for (const entry of readdirSync3(skillPath).sort()) {
21929
- const entryPath = join5(skillPath, entry);
21929
+ const entryPath = join4(skillPath, entry);
21930
21930
  if (RESERVED_SKILL_ENTRIES.has(entry)) {
21931
21931
  add(issues, "skill.reserved_file", `Reserved file '${entry}' is not allowed in skill packages`);
21932
21932
  }
@@ -21938,13 +21938,13 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21938
21938
  }
21939
21939
  }
21940
21940
  for (const docFile of DOC_FILES) {
21941
- if (existsSync4(join5(skillPath, docFile)))
21941
+ if (existsSync4(join4(skillPath, docFile)))
21942
21942
  metadata.docFiles.push(docFile);
21943
21943
  }
21944
21944
  if (metadata.docFiles.length === 0) {
21945
21945
  add(issues, "skill.docs_missing", "Missing documentation file: expected SKILL.md, README.md, or CLAUDE.md");
21946
21946
  }
21947
- const skillMdPath = join5(skillPath, "SKILL.md");
21947
+ const skillMdPath = join4(skillPath, "SKILL.md");
21948
21948
  if (existsSync4(skillMdPath)) {
21949
21949
  const frontmatter = parseSkillFrontmatter(readFileSync3(skillMdPath, "utf-8"));
21950
21950
  if (!frontmatter) {
@@ -21988,7 +21988,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21988
21988
  }
21989
21989
  metadata.kind = resolvedKind;
21990
21990
  const isInstruction = resolvedKind === "instruction";
21991
- const pkgPath = join5(skillPath, "package.json");
21991
+ const pkgPath = join4(skillPath, "package.json");
21992
21992
  if (!existsSync4(pkgPath)) {
21993
21993
  if (!isInstruction)
21994
21994
  add(issues, "package.missing", "Missing package.json");
@@ -22047,7 +22047,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
22047
22047
  add(issues, "package.bin_target_unsafe", `package.json bin '${command}' target '${target}' must stay inside the skill directory`);
22048
22048
  continue;
22049
22049
  }
22050
- const targetPath = join5(skillPath, target);
22050
+ const targetPath = join4(skillPath, target);
22051
22051
  if (!existsSync4(targetPath)) {
22052
22052
  add(warnings, "package.bin_target_missing", `package.json bin '${command}' target '${target}' is not present before build`);
22053
22053
  } else if (statSync3(targetPath).isDirectory()) {
@@ -22065,17 +22065,17 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
22065
22065
  metadata.runtime = "none";
22066
22066
  } else {
22067
22067
  metadata.runtime = hostedMetadata ? "hosted" : "local";
22068
- const srcDir = join5(skillPath, "src");
22068
+ const srcDir = join4(skillPath, "src");
22069
22069
  if (hostedMetadata) {
22070
22070
  if (existsSync4(srcDir)) {
22071
22071
  add(issues, "skill.hosted_source_forbidden", "Hosted metadata skills must not include local implementation source");
22072
22072
  }
22073
22073
  } else if (!existsSync4(srcDir)) {
22074
22074
  add(issues, "skill.src_missing", "Missing src/ directory");
22075
- } else if (!existsSync4(join5(srcDir, "index.ts")) && !existsSync4(join5(srcDir, "index.js"))) {
22075
+ } else if (!existsSync4(join4(srcDir, "index.ts")) && !existsSync4(join4(srcDir, "index.js"))) {
22076
22076
  add(issues, "skill.src_index_missing", "Missing src/index.ts or src/index.js");
22077
22077
  } else {
22078
- const indexPath = existsSync4(join5(srcDir, "index.ts")) ? join5(srcDir, "index.ts") : join5(srcDir, "index.js");
22078
+ const indexPath = existsSync4(join4(srcDir, "index.ts")) ? join4(srcDir, "index.ts") : join4(srcDir, "index.js");
22079
22079
  const size = statSync3(indexPath).size;
22080
22080
  if (size < 50)
22081
22081
  add(warnings, "skill.src_index_minimal", `Source entry point is very small (${size}B)`);
@@ -22094,7 +22094,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
22094
22094
  // src/lib/skill-hash.ts
22095
22095
  import { createHash } from "crypto";
22096
22096
  import { existsSync as existsSync5, readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
22097
- import { join as join6, sep } from "path";
22097
+ import { join as join5, sep } from "path";
22098
22098
  var CONTENT_HASH_ALGORITHM = "sha256";
22099
22099
  var HASH_EXCLUDE_DIRS = new Set([".git", "node_modules", "dist", "build", ".turbo"]);
22100
22100
  var HASH_COVERAGE = [
@@ -22153,7 +22153,7 @@ function collectBundleFiles(skillPath) {
22153
22153
  if (seen.has(entry))
22154
22154
  continue;
22155
22155
  seen.add(entry);
22156
- const absolute = join6(skillPath, entry);
22156
+ const absolute = join5(skillPath, entry);
22157
22157
  if (!existsSync5(absolute))
22158
22158
  continue;
22159
22159
  if (statSync4(absolute).isDirectory())
@@ -22167,7 +22167,7 @@ function collectDirectory(files, dir, rel) {
22167
22167
  for (const entry of readdirSync4(dir).sort()) {
22168
22168
  if (entry.startsWith("."))
22169
22169
  continue;
22170
- const absolute = join6(dir, entry);
22170
+ const absolute = join5(dir, entry);
22171
22171
  const childRel = `${rel}/${entry}`;
22172
22172
  let stats;
22173
22173
  try {
@@ -22394,7 +22394,7 @@ import {
22394
22394
  realpathSync,
22395
22395
  writeFileSync as writeFileSync2
22396
22396
  } from "fs";
22397
- import { basename, dirname as dirname2, join as join7, relative } from "path";
22397
+ import { basename, dirname as dirname2, join as join6, relative } from "path";
22398
22398
  var ANY_SEGMENT_COPY_EXCLUDES = new Set([
22399
22399
  ".git",
22400
22400
  ".DS_Store",
@@ -22437,9 +22437,9 @@ function normalizePortableSkillName(name) {
22437
22437
  return normalized;
22438
22438
  }
22439
22439
  function readPortableSkillManifest(skillPath, fallbackName = basename(skillPath)) {
22440
- const skillJsonPath = join7(skillPath, "skill.json");
22441
- const skillMdPath = join7(skillPath, "SKILL.md");
22442
- const pkgPath = join7(skillPath, "package.json");
22440
+ const skillJsonPath = join6(skillPath, "skill.json");
22441
+ const skillMdPath = join6(skillPath, "SKILL.md");
22442
+ const pkgPath = join6(skillPath, "package.json");
22443
22443
  const jsonManifest = existsSync6(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
22444
22444
  const frontmatter = existsSync6(skillMdPath) ? parseSkillFrontmatter(readFileSync5(skillMdPath, "utf-8")) ?? undefined : undefined;
22445
22445
  const pkg = existsSync6(pkgPath) ? readJsonObject(pkgPath) : undefined;
@@ -22488,7 +22488,7 @@ function createInstructionManifest(name, options) {
22488
22488
  }
22489
22489
  function writeInstructionSkillTemplate(skillPath, manifest) {
22490
22490
  mkdirSync2(skillPath, { recursive: true });
22491
- writeFileSync2(join7(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
22491
+ writeFileSync2(join6(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
22492
22492
  writeSkillJsonWithHash(skillPath, manifest);
22493
22493
  }
22494
22494
  function renderInstructionSkillMd(manifest) {
@@ -22537,12 +22537,12 @@ function createPortableManifest(name, options) {
22537
22537
  };
22538
22538
  }
22539
22539
  function writePortableSkillTemplate(skillPath, manifest) {
22540
- mkdirSync2(join7(skillPath, "src"), { recursive: true });
22541
- writeFileSync2(join7(skillPath, "SKILL.md"), renderSkillMd(manifest));
22542
- writeFileSync2(join7(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
22543
- writeFileSync2(join7(skillPath, "package.json"), renderPackageJson(manifest));
22544
- writeFileSync2(join7(skillPath, "tsconfig.json"), renderTsconfig());
22545
- writeFileSync2(join7(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
22540
+ mkdirSync2(join6(skillPath, "src"), { recursive: true });
22541
+ writeFileSync2(join6(skillPath, "SKILL.md"), renderSkillMd(manifest));
22542
+ writeFileSync2(join6(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
22543
+ writeFileSync2(join6(skillPath, "package.json"), renderPackageJson(manifest));
22544
+ writeFileSync2(join6(skillPath, "tsconfig.json"), renderTsconfig());
22545
+ writeFileSync2(join6(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
22546
22546
  writeSkillJsonWithHash(skillPath, manifest);
22547
22547
  }
22548
22548
  function fillContractDefaults(manifest, entrypoint) {
@@ -22567,7 +22567,7 @@ function writeSkillJsonWithHash(skillPath, manifest) {
22567
22567
  content_hash: undefined
22568
22568
  }
22569
22569
  };
22570
- writeFileSync2(join7(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
22570
+ writeFileSync2(join6(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
22571
22571
  `);
22572
22572
  const hash = computeContentHash(skillPath);
22573
22573
  const withHash = {
@@ -22577,12 +22577,12 @@ function writeSkillJsonWithHash(skillPath, manifest) {
22577
22577
  content_hash: hash
22578
22578
  }
22579
22579
  };
22580
- writeFileSync2(join7(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
22580
+ writeFileSync2(join6(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
22581
22581
  `);
22582
22582
  return withHash;
22583
22583
  }
22584
22584
  function readExistingSkillJson(skillPath) {
22585
- const path = join7(skillPath, "skill.json");
22585
+ const path = join6(skillPath, "skill.json");
22586
22586
  if (!existsSync6(path))
22587
22587
  return {};
22588
22588
  try {
@@ -22616,24 +22616,24 @@ function ensurePortableSkillFiles(skillPath, manifest) {
22616
22616
  tags: next.tags?.length ? next.tags : ["custom", next.name]
22617
22617
  };
22618
22618
  const entry = next.commands[0]?.entry ?? "src/index.ts";
22619
- if (entry && !existsSync6(join7(skillPath, entry))) {
22620
- mkdirSync2(dirname2(join7(skillPath, entry)), { recursive: true });
22621
- writeFileSync2(join7(skillPath, entry), renderEntrypoint(next));
22619
+ if (entry && !existsSync6(join6(skillPath, entry))) {
22620
+ mkdirSync2(dirname2(join6(skillPath, entry)), { recursive: true });
22621
+ writeFileSync2(join6(skillPath, entry), renderEntrypoint(next));
22622
22622
  }
22623
- if (!existsSync6(join7(skillPath, "SKILL.md")))
22624
- writeFileSync2(join7(skillPath, "SKILL.md"), renderSkillMd(next));
22623
+ if (!existsSync6(join6(skillPath, "SKILL.md")))
22624
+ writeFileSync2(join6(skillPath, "SKILL.md"), renderSkillMd(next));
22625
22625
  else
22626
- writeFileSync2(join7(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync5(join7(skillPath, "SKILL.md"), "utf-8"), next));
22627
- if (!existsSync6(join7(skillPath, "AGENTS.md")))
22628
- writeFileSync2(join7(skillPath, "AGENTS.md"), renderAgentsMd(next));
22626
+ writeFileSync2(join6(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync5(join6(skillPath, "SKILL.md"), "utf-8"), next));
22627
+ if (!existsSync6(join6(skillPath, "AGENTS.md")))
22628
+ writeFileSync2(join6(skillPath, "AGENTS.md"), renderAgentsMd(next));
22629
22629
  ensurePackageJson(skillPath, next);
22630
- if (!existsSync6(join7(skillPath, "tsconfig.json")))
22631
- writeFileSync2(join7(skillPath, "tsconfig.json"), renderTsconfig());
22630
+ if (!existsSync6(join6(skillPath, "tsconfig.json")))
22631
+ writeFileSync2(join6(skillPath, "tsconfig.json"), renderTsconfig());
22632
22632
  writeSkillJsonWithHash(skillPath, next);
22633
22633
  return readPortableSkillManifest(skillPath, next.name);
22634
22634
  }
22635
22635
  function ensurePackageJson(skillPath, manifest) {
22636
- const pkgPath = join7(skillPath, "package.json");
22636
+ const pkgPath = join6(skillPath, "package.json");
22637
22637
  const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
22638
22638
  const commandName = normalizePortableSkillName(first.name || manifest.name);
22639
22639
  const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
@@ -22680,8 +22680,8 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
22680
22680
  inputs: [],
22681
22681
  commands: []
22682
22682
  };
22683
- if (!existsSync6(join7(skillPath, "SKILL.md"))) {
22684
- writeFileSync2(join7(skillPath, "SKILL.md"), renderSkillMd(next));
22683
+ if (!existsSync6(join6(skillPath, "SKILL.md"))) {
22684
+ writeFileSync2(join6(skillPath, "SKILL.md"), renderSkillMd(next));
22685
22685
  }
22686
22686
  writeSkillJsonWithHash(skillPath, next);
22687
22687
  return readPortableSkillManifest(skillPath, next.name);
@@ -22964,18 +22964,18 @@ var LEGACY_CUSTOM_DIRNAME = "custom";
22964
22964
  function getPortableSkillsRoot(options = {}) {
22965
22965
  if (options.rootDir)
22966
22966
  return options.rootDir;
22967
- const appDir = options.homeDir ? join8(options.homeDir, ".hasna", "skills") : getDataDir();
22968
- const cache = join8(appDir, SKILLS_CACHE_DIRNAME);
22967
+ const appDir = options.homeDir ? join7(options.homeDir, ".hasna", "skills") : getDataDir();
22968
+ const cache = join7(appDir, SKILLS_CACHE_DIRNAME);
22969
22969
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
22970
22970
  return cache;
22971
- const installed = join8(appDir, INSTALLED_SKILLS_DIRNAME);
22971
+ const installed = join7(appDir, INSTALLED_SKILLS_DIRNAME);
22972
22972
  migrateLegacySkillLayout(appDir, installed);
22973
22973
  return installed;
22974
22974
  }
22975
22975
  function looksLikeSkillDirectory(path) {
22976
22976
  if (!safeIsDirectory(path))
22977
22977
  return false;
22978
- return existsSync7(join8(path, "SKILL.md")) || existsSync7(join8(path, "skill.json")) || existsSync7(join8(path, "package.json"));
22978
+ return existsSync7(join7(path, "SKILL.md")) || existsSync7(join7(path, "skill.json")) || existsSync7(join7(path, "package.json"));
22979
22979
  }
22980
22980
  function migrateLegacySkillLayout(appDir, installed) {
22981
22981
  if (!safeIsDirectory(appDir))
@@ -22985,7 +22985,7 @@ function migrateLegacySkillLayout(appDir, installed) {
22985
22985
  for (const entry of readdirSync5(appDir)) {
22986
22986
  if (entry.startsWith(".") || entry === INSTALLED_SKILLS_DIRNAME)
22987
22987
  continue;
22988
- const path = join8(appDir, entry);
22988
+ const path = join7(appDir, entry);
22989
22989
  if (entry === LEGACY_CUSTOM_DIRNAME) {
22990
22990
  if (!safeIsDirectory(path))
22991
22991
  continue;
@@ -22993,7 +22993,7 @@ function migrateLegacySkillLayout(appDir, installed) {
22993
22993
  for (const nested of readdirSync5(path)) {
22994
22994
  if (nested.startsWith("."))
22995
22995
  continue;
22996
- const nestedPath = join8(path, nested);
22996
+ const nestedPath = join7(path, nested);
22997
22997
  if (looksLikeSkillDirectory(nestedPath))
22998
22998
  candidates.push({ from: nestedPath, name: nested });
22999
22999
  }
@@ -23007,10 +23007,10 @@ function migrateLegacySkillLayout(appDir, installed) {
23007
23007
  return;
23008
23008
  }
23009
23009
  for (const { from, name } of candidates) {
23010
- const target = join8(installed, name);
23010
+ const target = join7(installed, name);
23011
23011
  if (existsSync7(target))
23012
23012
  continue;
23013
- const staging = join8(installed, `.migrating-${name}-${process.pid}`);
23013
+ const staging = join7(installed, `.migrating-${name}-${process.pid}`);
23014
23014
  try {
23015
23015
  rmSync(staging, { recursive: true, force: true });
23016
23016
  cpSync2(from, staging, { recursive: true, errorOnExist: false });
@@ -23023,7 +23023,7 @@ function migrateLegacySkillLayout(appDir, installed) {
23023
23023
  }
23024
23024
  }
23025
23025
  function getPortableSkillPath(name, options = {}) {
23026
- return join8(getPortableSkillsRoot(options), normalizePortableSkillName(name));
23026
+ return join7(getPortableSkillsRoot(options), normalizePortableSkillName(name));
23027
23027
  }
23028
23028
  function findPortableSkill(name, options = {}) {
23029
23029
  let normalized;
@@ -23049,7 +23049,7 @@ function listPortableSkills(options = {}) {
23049
23049
  for (const entry of readdirSync5(root).sort()) {
23050
23050
  if (entry.startsWith("."))
23051
23051
  continue;
23052
- const path = join8(root, entry);
23052
+ const path = join7(root, entry);
23053
23053
  if (!safeIsDirectory(path))
23054
23054
  continue;
23055
23055
  try {
@@ -23083,7 +23083,7 @@ function isOfficialSkillName(name) {
23083
23083
  function scaffoldPortableSkill(name, options = {}) {
23084
23084
  const skillName = normalizePortableSkillName(name);
23085
23085
  const root = getPortableSkillsRoot(options);
23086
- const skillPath = join8(root, skillName);
23086
+ const skillPath = join7(root, skillName);
23087
23087
  if (existsSync7(skillPath)) {
23088
23088
  if (!options.overwrite)
23089
23089
  throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
@@ -23114,7 +23114,7 @@ function portPortableSkill(sourcePath, options = {}) {
23114
23114
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
23115
23115
  }
23116
23116
  const root = getPortableSkillsRoot(options);
23117
- const destination = join8(root, skillName);
23117
+ const destination = join7(root, skillName);
23118
23118
  if (existsSync7(destination)) {
23119
23119
  if (!options.overwrite)
23120
23120
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
@@ -23144,8 +23144,8 @@ function validatePortableSkillDirectory(name, skillPath) {
23144
23144
  const warnings = [...base.warnings];
23145
23145
  let manifest;
23146
23146
  if (existsSync7(skillPath)) {
23147
- const skillJsonPath = join8(skillPath, "skill.json");
23148
- const skillMdPath = join8(skillPath, "SKILL.md");
23147
+ const skillJsonPath = join7(skillPath, "skill.json");
23148
+ const skillMdPath = join7(skillPath, "SKILL.md");
23149
23149
  if (!existsSync7(skillJsonPath) && !existsSync7(skillMdPath)) {
23150
23150
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
23151
23151
  }
@@ -23165,7 +23165,7 @@ function validatePortableSkillDirectory(name, skillPath) {
23165
23165
  add3(issues, "portable.version_missing", "Portable manifest missing version");
23166
23166
  }
23167
23167
  const contractIssues = validatePortableManifestContract(manifest, {
23168
- strict: existsSync7(join8(skillPath, "skill.json")),
23168
+ strict: existsSync7(join7(skillPath, "skill.json")),
23169
23169
  skillPath
23170
23170
  });
23171
23171
  for (const issue2 of contractIssues)
@@ -23201,7 +23201,7 @@ function validatePortableSkillDirectory(name, skillPath) {
23201
23201
  add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
23202
23202
  continue;
23203
23203
  }
23204
- const entryPath = join8(skillPath, command.entry);
23204
+ const entryPath = join7(skillPath, command.entry);
23205
23205
  if (!existsSync7(entryPath))
23206
23206
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
23207
23207
  else if (statSync6(entryPath).isDirectory())
@@ -23212,7 +23212,7 @@ function validatePortableSkillDirectory(name, skillPath) {
23212
23212
  } catch (error2) {
23213
23213
  add3(issues, "portable.manifest_invalid", error2.message);
23214
23214
  }
23215
- if (manifest?.kind !== "instruction" && !existsSync7(join8(skillPath, "AGENTS.md"))) {
23215
+ if (manifest?.kind !== "instruction" && !existsSync7(join7(skillPath, "AGENTS.md"))) {
23216
23216
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
23217
23217
  }
23218
23218
  }
@@ -23478,7 +23478,7 @@ function discoverSkillsInDir(dir, source = "custom") {
23478
23478
  for (const entry of entries) {
23479
23479
  if (!entry.isDirectory())
23480
23480
  continue;
23481
- const skillMdPath = join9(dir, entry.name, "SKILL.md");
23481
+ const skillMdPath = join8(dir, entry.name, "SKILL.md");
23482
23482
  if (!existsSync8(skillMdPath))
23483
23483
  continue;
23484
23484
  let content;
@@ -23498,7 +23498,7 @@ function discoverSkillsInDir(dir, source = "custom") {
23498
23498
  category: fm.category || "Development Tools",
23499
23499
  tags: fm.tags || [],
23500
23500
  ...fm.kind ? { kind: fm.kind } : {},
23501
- ...isHostedMetadataSkillDir(join9(dir, entry.name)) ? { serverOwned: true } : {},
23501
+ ...isHostedMetadataSkillDir(join8(dir, entry.name)) ? { serverOwned: true } : {},
23502
23502
  source
23503
23503
  });
23504
23504
  }
@@ -23514,8 +23514,8 @@ function findExtensionSkillPath(name) {
23514
23514
  for (const entry of entries) {
23515
23515
  if (!entry.isDirectory())
23516
23516
  continue;
23517
- const skillDir = join9(config2.extensionsDir, entry.name);
23518
- const skillMdPath = join9(skillDir, "SKILL.md");
23517
+ const skillDir = join8(config2.extensionsDir, entry.name);
23518
+ const skillMdPath = join8(skillDir, "SKILL.md");
23519
23519
  if (!existsSync8(skillMdPath))
23520
23520
  continue;
23521
23521
  let content;
@@ -23553,7 +23553,7 @@ function loadRegistry(cwd) {
23553
23553
  const official = SKILLS.map((s) => ({ ...s, source: "official" }));
23554
23554
  const extensions = config2.extensionsDir ? discoverSkillsInDir(config2.extensionsDir, "extension") : [];
23555
23555
  const portableCustom = listPortableSkillMetas();
23556
- const legacyCustom = discoverSkillsInDir(join9(dataDir2, "custom"));
23556
+ const legacyCustom = discoverSkillsInDir(join8(dataDir2, "custom"));
23557
23557
  const globalCustom = mergeCustomSkills([...legacyCustom, ...portableCustom]);
23558
23558
  registryCache = mergeSkillRegistryLists(official, extensions, globalCustom);
23559
23559
  registryCacheTime = now;
@@ -23590,8 +23590,8 @@ function mergeCustomSkills(skills) {
23590
23590
 
23591
23591
  // src/lib/installer.ts
23592
23592
  import { existsSync as existsSync10, readFileSync as readFileSync8, rmSync as rmSync2 } from "fs";
23593
- import { dirname as dirname4, join as join11 } from "path";
23594
- import { homedir as homedir4 } from "os";
23593
+ import { dirname as dirname4, join as join10 } from "path";
23594
+ import { homedir as homedir3 } from "os";
23595
23595
  import { fileURLToPath } from "url";
23596
23596
 
23597
23597
  // src/lib/home-migration.ts
@@ -23608,7 +23608,7 @@ init_config();
23608
23608
 
23609
23609
  // src/lib/project-state.ts
23610
23610
  import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
23611
- import { join as join10 } from "path";
23611
+ import { join as join9 } from "path";
23612
23612
  var VALID_PIN_SOURCES = [
23613
23613
  "official",
23614
23614
  "custom",
@@ -23623,10 +23623,10 @@ var SKILLS_PROJECT_DIR = ".skills";
23623
23623
  var PROJECT_CONFIG_FILE = "project.json";
23624
23624
  var DEFAULT_EXPORT_DIR = ".skills/exports";
23625
23625
  function getProjectStateDir(targetDir = process.cwd()) {
23626
- return join10(targetDir, SKILLS_PROJECT_DIR);
23626
+ return join9(targetDir, SKILLS_PROJECT_DIR);
23627
23627
  }
23628
23628
  function getProjectConfigPath(targetDir = process.cwd()) {
23629
- return join10(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
23629
+ return join9(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
23630
23630
  }
23631
23631
  function loadProjectConfig(targetDir = process.cwd()) {
23632
23632
  const path = getProjectConfigPath(targetDir);
@@ -23732,12 +23732,12 @@ var __dirname2 = dirname4(fileURLToPath(import.meta.url));
23732
23732
  function findSkillsDir() {
23733
23733
  let dir = __dirname2;
23734
23734
  for (let i = 0;i < 5; i++) {
23735
- const candidate = join11(dir, "skills");
23735
+ const candidate = join10(dir, "skills");
23736
23736
  if (existsSync10(candidate) && !dir.includes(".skills"))
23737
23737
  return candidate;
23738
23738
  dir = dirname4(dir);
23739
23739
  }
23740
- return join11(__dirname2, "..", "skills");
23740
+ return join10(__dirname2, "..", "skills");
23741
23741
  }
23742
23742
  var SKILLS_DIR = findSkillsDir();
23743
23743
  function getSkillPath(name) {
@@ -23745,13 +23745,13 @@ function getSkillPath(name) {
23745
23745
  const portable = findPortableSkill(skillName);
23746
23746
  if (portable)
23747
23747
  return portable.path;
23748
- const legacyCustomPath = join11(getDataDir(), "custom", skillName);
23748
+ const legacyCustomPath = join10(getDataDir(), "custom", skillName);
23749
23749
  if (existsSync10(legacyCustomPath))
23750
23750
  return legacyCustomPath;
23751
23751
  const extensionPath = findExtensionSkillPath(skillName);
23752
23752
  if (extensionPath)
23753
23753
  return extensionPath;
23754
- return join11(SKILLS_DIR, skillName);
23754
+ return join10(SKILLS_DIR, skillName);
23755
23755
  }
23756
23756
  function getCanonicalSkillName(name) {
23757
23757
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
@@ -23815,11 +23815,11 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
23815
23815
  const base = projectDir || process.cwd();
23816
23816
  switch (agent) {
23817
23817
  case "pi":
23818
- return scope === "project" ? join11(base, ".pi", "skills") : join11(homedir4(), ".pi", "agent", "skills");
23818
+ return scope === "project" ? join10(base, ".pi", "skills") : join10(homedir3(), ".pi", "agent", "skills");
23819
23819
  case "opencode":
23820
- return scope === "project" ? join11(base, ".opencode", "skills") : join11(homedir4(), ".config", "opencode", "skills");
23820
+ return scope === "project" ? join10(base, ".opencode", "skills") : join10(homedir3(), ".config", "opencode", "skills");
23821
23821
  default:
23822
- return scope === "project" ? join11(base, `.${agent}`, "skills") : join11(homedir4(), `.${agent}`, "skills");
23822
+ return scope === "project" ? join10(base, `.${agent}`, "skills") : join10(homedir3(), `.${agent}`, "skills");
23823
23823
  }
23824
23824
  }
23825
23825
  function warnMissingDependencies(name, targetDir) {
@@ -23834,7 +23834,7 @@ function warnMissingDependencies(name, targetDir) {
23834
23834
  }
23835
23835
  }
23836
23836
  function readBundledSkillVersion(name) {
23837
- const pkgPath = join11(getSkillPath(name), "package.json");
23837
+ const pkgPath = join10(getSkillPath(name), "package.json");
23838
23838
  if (!existsSync10(pkgPath))
23839
23839
  return "unknown";
23840
23840
  try {
@@ -23847,11 +23847,11 @@ function readBundledSkillVersion(name) {
23847
23847
 
23848
23848
  // src/lib/skillinfo.ts
23849
23849
  import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
23850
- import { join as join12 } from "path";
23850
+ import { join as join11 } from "path";
23851
23851
  function isInstructionSkillDir(skillPath, meta) {
23852
23852
  if (meta?.kind === "instruction")
23853
23853
  return true;
23854
- const skillMdPath = join12(skillPath, "SKILL.md");
23854
+ const skillMdPath = join11(skillPath, "SKILL.md");
23855
23855
  if (!existsSync11(skillMdPath))
23856
23856
  return false;
23857
23857
  try {
@@ -23881,9 +23881,9 @@ function getSkillDocs(name) {
23881
23881
  if (!existsSync11(skillPath))
23882
23882
  return null;
23883
23883
  return {
23884
- skillMd: readIfExists(join12(skillPath, "SKILL.md")),
23885
- readme: readIfExists(join12(skillPath, "README.md")),
23886
- claudeMd: readIfExists(join12(skillPath, "CLAUDE.md"))
23884
+ skillMd: readIfExists(join11(skillPath, "SKILL.md")),
23885
+ readme: readIfExists(join11(skillPath, "README.md")),
23886
+ claudeMd: readIfExists(join11(skillPath, "CLAUDE.md"))
23887
23887
  };
23888
23888
  }
23889
23889
  function getSkillBestDoc(name) {
@@ -23898,7 +23898,7 @@ function getSkillRequirements(name) {
23898
23898
  return null;
23899
23899
  const texts = [];
23900
23900
  for (const file of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
23901
- const content = readIfExists(join12(skillPath, file));
23901
+ const content = readIfExists(join11(skillPath, file));
23902
23902
  if (content)
23903
23903
  texts.push(content);
23904
23904
  }
@@ -23937,7 +23937,7 @@ function getSkillRequirements(name) {
23937
23937
  const skillName = normalizeSkillName(name);
23938
23938
  let cliCommand = `skills run ${skillName}`;
23939
23939
  let dependencies = {};
23940
- const pkgPath = join12(skillPath, "package.json");
23940
+ const pkgPath = join11(skillPath, "package.json");
23941
23941
  if (existsSync11(pkgPath)) {
23942
23942
  try {
23943
23943
  const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
@@ -23967,7 +23967,7 @@ async function runSkill(name, args, options = {}) {
23967
23967
  error: `Skill '${name}' is an instruction skill (kind: instruction) and is not runnable. Instruction skills are consumed by coding agents via SKILL.md, not executed with 'skills run'.`
23968
23968
  };
23969
23969
  }
23970
- const pkgPath = join12(skillPath, "package.json");
23970
+ const pkgPath = join11(skillPath, "package.json");
23971
23971
  if (!existsSync11(pkgPath)) {
23972
23972
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
23973
23973
  }
@@ -23987,11 +23987,11 @@ async function runSkill(name, args, options = {}) {
23987
23987
  } catch {
23988
23988
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
23989
23989
  }
23990
- const entryPath = join12(skillPath, entryPoint);
23990
+ const entryPath = join11(skillPath, entryPoint);
23991
23991
  if (!existsSync11(entryPath)) {
23992
23992
  return { exitCode: 1, error: `Entry point '${entryPoint}' not found in skill '${name}'` };
23993
23993
  }
23994
- const nodeModules = join12(skillPath, "node_modules");
23994
+ const nodeModules = join11(skillPath, "node_modules");
23995
23995
  if (!existsSync11(nodeModules)) {
23996
23996
  const install = Bun.spawn(["bun", "install", "--no-save"], {
23997
23997
  cwd: skillPath,
@@ -24019,7 +24019,7 @@ async function runSkill(name, args, options = {}) {
24019
24019
  return { exitCode };
24020
24020
  }
24021
24021
  function detectProjectSkills(cwd = process.cwd()) {
24022
- const pkgPath = join12(cwd, "package.json");
24022
+ const pkgPath = join11(cwd, "package.json");
24023
24023
  if (!existsSync11(pkgPath)) {
24024
24024
  const alwaysRecommend = ["market-research-report", "repo-onboarding-report", "blog-article"];
24025
24025
  const recommended2 = alwaysRecommend.map((name) => loadRegistry().find((s) => s.name === name)).filter((s) => s !== undefined);
@@ -25700,24 +25700,24 @@ function registerDiscoveryTools(server) {
25700
25700
 
25701
25701
  // src/mcp/operation-tools.ts
25702
25702
  import { existsSync as existsSync14, readdirSync as readdirSync8, statSync as statSync8 } from "fs";
25703
- import { join as join15 } from "path";
25703
+ import { join as join14 } from "path";
25704
25704
 
25705
25705
  // src/lib/run-state.ts
25706
25706
  import { createHash as createHash2, randomBytes } from "crypto";
25707
25707
  import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync10, readdirSync as readdirSync7, statSync as statSync7, writeFileSync as writeFileSync5 } from "fs";
25708
- import { extname, join as join13, relative as relative2 } from "path";
25708
+ import { extname, join as join12, relative as relative2 } from "path";
25709
25709
  function createSkillRun(params, targetDir = process.cwd()) {
25710
25710
  const now = new Date;
25711
25711
  const id = createRunId(now);
25712
25712
  const day = now.toISOString().slice(0, 10);
25713
25713
  const skillName = normalizeSkillName(params.skill);
25714
25714
  const root = getProjectStateDir(targetDir);
25715
- const runDir = join13(root, "runs", day, id);
25716
- const logsDir = join13(runDir, "logs");
25717
- const exportDir = join13(root, "exports", skillName, id);
25715
+ const runDir = join12(root, "runs", day, id);
25716
+ const logsDir = join12(runDir, "logs");
25717
+ const exportDir = join12(root, "exports", skillName, id);
25718
25718
  mkdirSync5(logsDir, { recursive: true });
25719
25719
  mkdirSync5(exportDir, { recursive: true });
25720
- mkdirSync5(join13(root, "tmp"), { recursive: true });
25720
+ mkdirSync5(join12(root, "tmp"), { recursive: true });
25721
25721
  const record3 = {
25722
25722
  id,
25723
25723
  skill: skillName,
@@ -25768,22 +25768,22 @@ function updateSkillRun(context, patch) {
25768
25768
  return context.record;
25769
25769
  }
25770
25770
  function writeRunLogs(context, stdout = "", stderr = "") {
25771
- writeFileSync5(join13(context.logsDir, "stdout.log"), stdout);
25772
- writeFileSync5(join13(context.logsDir, "stderr.log"), stderr);
25771
+ writeFileSync5(join12(context.logsDir, "stdout.log"), stdout);
25772
+ writeFileSync5(join12(context.logsDir, "stderr.log"), stderr);
25773
25773
  }
25774
25774
  function appendRunEvent(context, event, data = {}) {
25775
25775
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
25776
25776
  `;
25777
- const path = join13(context.runDir, "events.ndjson");
25777
+ const path = join12(context.runDir, "events.ndjson");
25778
25778
  const previous = existsSync12(path) ? readFileSync10(path, "utf-8") : "";
25779
25779
  writeFileSync5(path, previous + line);
25780
25780
  }
25781
25781
  function findSkillRun(runId, targetDir = process.cwd()) {
25782
- const runsRoot = join13(getProjectStateDir(targetDir), "runs");
25782
+ const runsRoot = join12(getProjectStateDir(targetDir), "runs");
25783
25783
  if (!existsSync12(runsRoot))
25784
25784
  return null;
25785
25785
  for (const day of readdirSync7(runsRoot)) {
25786
- const record3 = readRunRecord(join13(runsRoot, day, runId));
25786
+ const record3 = readRunRecord(join12(runsRoot, day, runId));
25787
25787
  if (record3)
25788
25788
  return record3;
25789
25789
  }
@@ -25800,11 +25800,11 @@ function skillRunEnv(context) {
25800
25800
  };
25801
25801
  }
25802
25802
  function writeRunRecord(context) {
25803
- writeFileSync5(join13(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
25803
+ writeFileSync5(join12(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
25804
25804
  `);
25805
25805
  }
25806
25806
  function writeArtifactsManifest(context, artifacts) {
25807
- writeFileSync5(join13(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
25807
+ writeFileSync5(join12(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
25808
25808
  `);
25809
25809
  }
25810
25810
  function collectRunArtifacts(context) {
@@ -25824,7 +25824,7 @@ function collectRunArtifacts(context) {
25824
25824
  return artifacts.sort((a, b) => a.path.localeCompare(b.path));
25825
25825
  }
25826
25826
  function readRunRecord(runDir) {
25827
- const path = join13(runDir, "run.json");
25827
+ const path = join12(runDir, "run.json");
25828
25828
  if (!existsSync12(path))
25829
25829
  return null;
25830
25830
  try {
@@ -25836,7 +25836,7 @@ function readRunRecord(runDir) {
25836
25836
  function walkFiles(dir) {
25837
25837
  const files = [];
25838
25838
  for (const entry of readdirSync7(dir)) {
25839
- const full = join13(dir, entry);
25839
+ const full = join12(dir, entry);
25840
25840
  if (statSync7(full).isDirectory())
25841
25841
  files.push(...walkFiles(full));
25842
25842
  else
@@ -26312,7 +26312,7 @@ function registerOperationTools(server) {
26312
26312
  if (exists) {
26313
26313
  try {
26314
26314
  skillCount = readdirSync8(agentSkillsPath).filter((f) => {
26315
- const full = join15(agentSkillsPath, f);
26315
+ const full = join14(agentSkillsPath, f);
26316
26316
  return !f.startsWith(".") && statSync8(full).isDirectory();
26317
26317
  }).length;
26318
26318
  } catch {}
@@ -26358,12 +26358,13 @@ function compactRunToolPayload(payload, detailHint) {
26358
26358
  }
26359
26359
 
26360
26360
  // src/lib/feedback.ts
26361
+ init_api_url();
26361
26362
  init_config();
26362
- import { existsSync as existsSync15, mkdirSync as mkdirSync7 } from "fs";
26363
- import { dirname as dirname6, join as join16 } from "path";
26363
+ import { appendFileSync, existsSync as existsSync15, mkdirSync as mkdirSync7 } from "fs";
26364
+ import { dirname as dirname6, join as join15 } from "path";
26364
26365
  import { Database } from "bun:sqlite";
26365
26366
  function getFeedbackDbPath() {
26366
- return join16(getDataDir(), "skills.db");
26367
+ return join15(getDataDir(), "skills.db");
26367
26368
  }
26368
26369
  function getFeedbackDb() {
26369
26370
  const dbPath = getFeedbackDbPath();
@@ -26394,6 +26395,15 @@ function saveFeedback(input) {
26394
26395
  if (!message)
26395
26396
  throw new Error("Feedback message is required");
26396
26397
  const category = input.category ?? "general";
26398
+ if (isApiMode()) {
26399
+ const path = join15(getDataDir(), "feedback.jsonl");
26400
+ const dir = dirname6(path);
26401
+ if (!existsSync15(dir))
26402
+ mkdirSync7(dir, { recursive: true });
26403
+ appendFileSync(path, JSON.stringify({ message, category, email: input.email ?? null, agent: input.agent ?? null, version: input.version ?? null, createdAt: new Date().toISOString() }) + `
26404
+ `);
26405
+ return { saved: true, category, path };
26406
+ }
26397
26407
  const db = getFeedbackDb();
26398
26408
  try {
26399
26409
  db.run("INSERT INTO feedback (message, email, category, agent, version) VALUES (?, ?, ?, ?, ?)", [message, input.email || null, category, input.agent || null, input.version || null]);
@@ -26402,6 +26412,15 @@ function saveFeedback(input) {
26402
26412
  }
26403
26413
  return { saved: true, category, path: getFeedbackDbPath() };
26404
26414
  }
26415
+ function isApiMode(env = process.env) {
26416
+ if (env.HASNA_SKILLS_API_URL?.trim())
26417
+ return true;
26418
+ try {
26419
+ return Boolean(resolveApiUrl(undefined, env));
26420
+ } catch {
26421
+ return Boolean(env.SKILLS_API_URL?.trim());
26422
+ }
26423
+ }
26405
26424
 
26406
26425
  // src/mcp/resource-meta-tools.ts
26407
26426
  function registerResourceMetaTools(server) {
@@ -26528,9 +26547,9 @@ function registerResourceMetaTools(server) {
26528
26547
 
26529
26548
  // src/lib/scheduler.ts
26530
26549
  import { existsSync as existsSync16, readFileSync as readFileSync12, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8 } from "fs";
26531
- import { join as join17 } from "path";
26550
+ import { join as join16 } from "path";
26532
26551
  function getSchedulesPath(targetDir = process.cwd()) {
26533
- return join17(targetDir, ".skills", "schedules.json");
26552
+ return join16(targetDir, ".skills", "schedules.json");
26534
26553
  }
26535
26554
  function loadSchedules(targetDir = process.cwd()) {
26536
26555
  const path = getSchedulesPath(targetDir);
@@ -26543,7 +26562,7 @@ function loadSchedules(targetDir = process.cwd()) {
26543
26562
  }
26544
26563
  function saveSchedules(data, targetDir = process.cwd()) {
26545
26564
  const path = getSchedulesPath(targetDir);
26546
- const dir = join17(targetDir, ".skills");
26565
+ const dir = join16(targetDir, ".skills");
26547
26566
  if (!existsSync16(dir))
26548
26567
  mkdirSync8(dir, { recursive: true });
26549
26568
  writeFileSync7(path, JSON.stringify(data, null, 2));
@@ -26814,7 +26833,7 @@ import {
26814
26833
  statSync as statSync9,
26815
26834
  writeFileSync as writeFileSync8
26816
26835
  } from "fs";
26817
- import { dirname as dirname7, join as join18, normalize as normalize3, relative as relative3, sep as sep2 } from "path";
26836
+ import { dirname as dirname7, join as join17, normalize as normalize3, relative as relative3, sep as sep2 } from "path";
26818
26837
  init_retired_settings();
26819
26838
  var SKILLS_STORAGE_TABLES = [
26820
26839
  "skills_sync_records",
@@ -26891,7 +26910,7 @@ function getSkillsNativeStorageStatus(options = {}) {
26891
26910
  local: {
26892
26911
  dataDir: getDataDir(),
26893
26912
  projectStateDir: getProjectStateDir(targetDir),
26894
- feedbackDbPath: join18(getDataDir(), "skills.db")
26913
+ feedbackDbPath: join17(getDataDir(), "skills.db")
26895
26914
  },
26896
26915
  remote: {
26897
26916
  databaseConfigured: Boolean(config2.databaseUrl),
@@ -26995,7 +27014,7 @@ function parsePositiveInteger(value) {
26995
27014
  function walkFiles2(dir) {
26996
27015
  const files = [];
26997
27016
  for (const entry of readdirSync9(dir)) {
26998
- const full = join18(dir, entry);
27017
+ const full = join17(dir, entry);
26999
27018
  const stats = statSync9(full);
27000
27019
  if (stats.isDirectory())
27001
27020
  files.push(...walkFiles2(full));