@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/README.md +4 -2
- package/bin/index.js +24514 -24319
- package/bin/mcp.js +217 -198
- package/bin/migrate.js +114 -62
- package/bin/server.js +3384 -2892
- package/bin/worker.js +2095 -1820
- package/dist/cli/commands/install.d.ts +16 -0
- package/dist/cli/commands/publish.d.ts +35 -0
- package/dist/cli/commands/registry.d.ts +5 -0
- package/dist/index.js +475 -263
- package/dist/lib/app-home.d.ts +27 -1
- package/dist/lib/feedback.d.ts +6 -0
- package/dist/lib/installer.d.ts +2 -0
- package/dist/lib/pull.d.ts +18 -1
- package/dist/lib/remote-client.d.ts +15 -1
- package/dist/lib/skill-version.d.ts +11 -0
- package/dist/sdk/index.js +5470 -4975
- package/dist/server/app.d.ts +3 -0
- package/dist/server/artifact-storage.d.ts +27 -0
- package/dist/server/config.d.ts +2 -0
- package/dist/server/rows.d.ts +2 -1
- package/dist/server/seed-bundled.d.ts +20 -0
- package/dist/server/skills-api.d.ts +18 -1
- package/dist/server/sqlite-store.d.ts +3 -1
- package/dist/server/store.d.ts +6 -1
- package/dist/server/types.d.ts +43 -0
- package/dist/storage.js +62 -61
- package/migrations/postgres/0006_skill_versions.sql +30 -0
- package/migrations/sqlite/0006_skill_versions.sql +17 -0
- package/package.json +2 -3
package/bin/mcp.js
CHANGED
|
@@ -6679,92 +6679,77 @@ var init_retired_settings = __esm(() => {
|
|
|
6679
6679
|
};
|
|
6680
6680
|
});
|
|
6681
6681
|
|
|
6682
|
-
//
|
|
6682
|
+
// src/lib/app-home.ts
|
|
6683
|
+
import { existsSync } from "fs";
|
|
6683
6684
|
import { homedir } from "os";
|
|
6684
|
-
import { join } from "path";
|
|
6685
|
-
|
|
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 (!
|
|
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
|
|
6694
|
-
|
|
6695
|
-
}
|
|
6696
|
-
|
|
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
|
|
6704
|
-
|
|
6705
|
-
|
|
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 ??
|
|
6707
|
+
const home = options.home ?? pathsResolverHomedir();
|
|
6708
6708
|
const platform = options.platform ?? process.platform;
|
|
6709
|
-
if (
|
|
6709
|
+
if (platform === "darwin") {
|
|
6710
6710
|
switch (kind) {
|
|
6711
6711
|
case "config":
|
|
6712
6712
|
case "data":
|
|
6713
|
-
return
|
|
6713
|
+
return pathsResolverJoin(home, "Library", "Application Support", "Hasna");
|
|
6714
6714
|
case "cache":
|
|
6715
|
-
return
|
|
6715
|
+
return pathsResolverJoin(home, "Library", "Caches", "Hasna");
|
|
6716
6716
|
case "state":
|
|
6717
|
-
return
|
|
6717
|
+
return pathsResolverJoin(home, "Library", "Logs", "Hasna");
|
|
6718
6718
|
}
|
|
6719
6719
|
}
|
|
6720
6720
|
switch (kind) {
|
|
6721
6721
|
case "config":
|
|
6722
|
-
return
|
|
6722
|
+
return pathsResolverJoin(home, ".config", "hasna");
|
|
6723
6723
|
case "data":
|
|
6724
|
-
return
|
|
6724
|
+
return pathsResolverJoin(home, ".local", "share", "hasna");
|
|
6725
6725
|
case "state":
|
|
6726
|
-
return
|
|
6726
|
+
return pathsResolverJoin(home, ".local", "state", "hasna");
|
|
6727
6727
|
case "cache":
|
|
6728
|
-
return
|
|
6728
|
+
return pathsResolverJoin(home, ".cache", "hasna");
|
|
6729
6729
|
}
|
|
6730
6730
|
}
|
|
6731
|
-
function
|
|
6732
|
-
|
|
6733
|
-
const appSegment = options.internal === true ?
|
|
6734
|
-
return
|
|
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
|
|
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"] ||
|
|
6740
|
+
return process.env["HOME"] || process.env["USERPROFILE"] || homedir() || "/tmp";
|
|
6756
6741
|
}
|
|
6757
6742
|
function legacyDataRoot() {
|
|
6758
|
-
return
|
|
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(
|
|
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
|
-
|
|
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
|
|
6798
|
-
import { homedir as
|
|
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 =
|
|
6811
|
-
const targetPath =
|
|
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(
|
|
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 =
|
|
6855
|
-
const oldConfigFile =
|
|
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(
|
|
6850
|
+
if (existsSync2(oldConfigFile) && !existsSync2(join2(root, "config.json"))) {
|
|
6860
6851
|
try {
|
|
6861
|
-
copyFileSync(oldConfigFile,
|
|
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
|
|
6872
|
-
return
|
|
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
|
|
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
|
|
6883
|
+
return join2(getDataDir(), "config.json");
|
|
6893
6884
|
}
|
|
6894
|
-
return
|
|
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
|
|
7019
|
-
import { homedir as
|
|
7009
|
+
import { dirname as dirname5, join as join13 } from "path";
|
|
7010
|
+
import { homedir as homedir4 } from "os";
|
|
7020
7011
|
function getAuthFilePath() {
|
|
7021
|
-
return
|
|
7012
|
+
return join13(getDataDir(), "auth.json");
|
|
7022
7013
|
}
|
|
7023
7014
|
function getAuthFilePathReadOnly() {
|
|
7024
|
-
return
|
|
7015
|
+
return join13(getDataDirReadOnly(), "auth.json");
|
|
7025
7016
|
}
|
|
7026
7017
|
function legacyAuthFilePath() {
|
|
7027
|
-
return
|
|
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
|
|
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.
|
|
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": "
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
22441
|
-
const skillMdPath =
|
|
22442
|
-
const pkgPath =
|
|
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(
|
|
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(
|
|
22541
|
-
writeFileSync2(
|
|
22542
|
-
writeFileSync2(
|
|
22543
|
-
writeFileSync2(
|
|
22544
|
-
writeFileSync2(
|
|
22545
|
-
writeFileSync2(
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
22620
|
-
mkdirSync2(dirname2(
|
|
22621
|
-
writeFileSync2(
|
|
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(
|
|
22624
|
-
writeFileSync2(
|
|
22623
|
+
if (!existsSync6(join6(skillPath, "SKILL.md")))
|
|
22624
|
+
writeFileSync2(join6(skillPath, "SKILL.md"), renderSkillMd(next));
|
|
22625
22625
|
else
|
|
22626
|
-
writeFileSync2(
|
|
22627
|
-
if (!existsSync6(
|
|
22628
|
-
writeFileSync2(
|
|
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(
|
|
22631
|
-
writeFileSync2(
|
|
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 =
|
|
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(
|
|
22684
|
-
writeFileSync2(
|
|
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 ?
|
|
22968
|
-
const cache =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
23010
|
+
const target = join7(installed, name);
|
|
23011
23011
|
if (existsSync7(target))
|
|
23012
23012
|
continue;
|
|
23013
|
-
const staging =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
23148
|
-
const skillMdPath =
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
23518
|
-
const skillMdPath =
|
|
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(
|
|
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
|
|
23594
|
-
import { homedir as
|
|
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
|
|
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
|
|
23626
|
+
return join9(targetDir, SKILLS_PROJECT_DIR);
|
|
23627
23627
|
}
|
|
23628
23628
|
function getProjectConfigPath(targetDir = process.cwd()) {
|
|
23629
|
-
return
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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" ?
|
|
23818
|
+
return scope === "project" ? join10(base, ".pi", "skills") : join10(homedir3(), ".pi", "agent", "skills");
|
|
23819
23819
|
case "opencode":
|
|
23820
|
-
return scope === "project" ?
|
|
23820
|
+
return scope === "project" ? join10(base, ".opencode", "skills") : join10(homedir3(), ".config", "opencode", "skills");
|
|
23821
23821
|
default:
|
|
23822
|
-
return scope === "project" ?
|
|
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 =
|
|
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
|
|
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 =
|
|
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(
|
|
23885
|
-
readme: readIfExists(
|
|
23886
|
-
claudeMd: readIfExists(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
25716
|
-
const logsDir =
|
|
25717
|
-
const exportDir =
|
|
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(
|
|
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(
|
|
25772
|
-
writeFileSync5(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
26550
|
+
import { join as join16 } from "path";
|
|
26532
26551
|
function getSchedulesPath(targetDir = process.cwd()) {
|
|
26533
|
-
return
|
|
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 =
|
|
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
|
|
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:
|
|
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 =
|
|
27017
|
+
const full = join17(dir, entry);
|
|
26999
27018
|
const stats = statSync9(full);
|
|
27000
27019
|
if (stats.isDirectory())
|
|
27001
27020
|
files.push(...walkFiles2(full));
|