@hasna/skills 0.1.70 → 0.1.72

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/dist/sdk/index.js CHANGED
@@ -22937,19 +22937,15 @@ var init_dist_es9 = __esm(() => {
22937
22937
  init_fromIni();
22938
22938
  });
22939
22939
 
22940
- // ../events/dist/index.js
22940
+ // ../../node_modules/.bun/@hasna+events@0.1.16/node_modules/@hasna/events/dist/index.js
22941
22941
  import { chmod, mkdir, readFile, rename, writeFile as writeFile2 } from "fs/promises";
22942
22942
  import { Buffer as Buffer2 } from "buffer";
22943
- import { existsSync as existsSync14 } from "fs";
22944
- import { homedir as homedir5 } from "os";
22945
- import { join as join16 } from "path";
22943
+ import { existsSync as existsSync15 } from "fs";
22944
+ import { homedir as homedir6 } from "os";
22945
+ import { join as join18 } from "path";
22946
22946
  import { createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
22947
- import { lookup as dnsLookup } from "dns/promises";
22948
- import { isIP } from "net";
22949
22947
  import { randomUUID as randomUUID5 } from "crypto";
22950
22948
  import { spawn } from "child_process";
22951
- import { request as nodeHttpRequest } from "http";
22952
- import { request as nodeHttpsRequest } from "https";
22953
22949
  import { randomUUID as randomUUID22 } from "crypto";
22954
22950
  function getPathValue(input, path) {
22955
22951
  return path.split(".").reduce((value, part) => {
@@ -23047,7 +23043,7 @@ function channelMatchesEvent(channel, event) {
23047
23043
  return channel.filters.some((filter) => eventMatchesFilter(event, filter));
23048
23044
  }
23049
23045
  function getEventsDataDir(override) {
23050
- return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join16(homedir5(), ".hasna", "events");
23046
+ return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join18(homedir6(), ".hasna", "events");
23051
23047
  }
23052
23048
 
23053
23049
  class JsonEventsStore {
@@ -23056,12 +23052,12 @@ class JsonEventsStore {
23056
23052
  channelsPath;
23057
23053
  eventsPath;
23058
23054
  deliveriesPath;
23059
- constructor(dataDir = getEventsDataDir()) {
23060
- this.dataDir = dataDir;
23061
- this.runtime = localJsonRuntime(dataDir);
23062
- this.channelsPath = join16(dataDir, "channels.json");
23063
- this.eventsPath = join16(dataDir, "events.json");
23064
- this.deliveriesPath = join16(dataDir, "deliveries.json");
23055
+ constructor(dataDir2 = getEventsDataDir()) {
23056
+ this.dataDir = dataDir2;
23057
+ this.runtime = localJsonRuntime(dataDir2);
23058
+ this.channelsPath = join18(dataDir2, "channels.json");
23059
+ this.eventsPath = join18(dataDir2, "events.json");
23060
+ this.deliveriesPath = join18(dataDir2, "deliveries.json");
23065
23061
  }
23066
23062
  async init() {
23067
23063
  await mkdir(this.dataDir, { recursive: true, mode: 448 });
@@ -23178,7 +23174,7 @@ class JsonEventsStore {
23178
23174
  };
23179
23175
  }
23180
23176
  async ensureArrayFile(path) {
23181
- if (!existsSync14(path)) {
23177
+ if (!existsSync15(path)) {
23182
23178
  await writeFile2(path, `[]
23183
23179
  `, { encoding: "utf-8", mode: 384 });
23184
23180
  }
@@ -23208,7 +23204,7 @@ class JsonEventsStore {
23208
23204
  });
23209
23205
  }
23210
23206
  }
23211
- function localJsonRuntime(dataDir = getEventsDataDir()) {
23207
+ function localJsonRuntime(dataDir2 = getEventsDataDir()) {
23212
23208
  return {
23213
23209
  mode: "local-files",
23214
23210
  name: "json-events-store",
@@ -23221,7 +23217,7 @@ function localJsonRuntime(dataDir = getEventsDataDir()) {
23221
23217
  durable: true,
23222
23218
  idempotency: "best-effort-local",
23223
23219
  replayCursors: true,
23224
- description: `Local JSON files in ${dataDir}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
23220
+ description: `Local JSON files in ${dataDir2}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
23225
23221
  };
23226
23222
  }
23227
23223
  function encodeLocalJsonEventCursor(offset, options = {}) {
@@ -23292,177 +23288,6 @@ function signPayload(secret, timestamp, body) {
23292
23288
  const digest2 = createHmac3("sha256", secret).update(buildSignatureBase(timestamp, body)).digest("hex");
23293
23289
  return `sha256=${digest2}`;
23294
23290
  }
23295
- function isPrivateAddress(address) {
23296
- const normalized = stripZoneId(address);
23297
- const version2 = isIP(normalized);
23298
- if (version2 === 4) {
23299
- const integer = ipv4ToInt(normalized);
23300
- if (integer === undefined)
23301
- return true;
23302
- return IPV4_PRIVATE_RANGES.some(([low, high]) => integer >= low && integer <= high);
23303
- }
23304
- if (version2 === 6) {
23305
- const groups = ipv6Groups(normalized);
23306
- if (!groups)
23307
- return true;
23308
- for (const prefix of IPV6_SPECIAL_PREFIXES) {
23309
- if (!ipv6MatchesPrefix(groups, prefix.groups, prefix.bits))
23310
- continue;
23311
- if (prefix.bits === 96 && groups[5] === 65535) {
23312
- return isPrivateAddress(ipv4IntToString(groups[6] << 16 | groups[7]));
23313
- }
23314
- if (prefix.bits === 16 && groups[0] === 8194) {
23315
- return isPrivateAddress(ipv4IntToString(groups[1] << 16 | groups[2]));
23316
- }
23317
- return true;
23318
- }
23319
- return false;
23320
- }
23321
- return true;
23322
- }
23323
- async function resolveWebhookTarget(url, policy = {}) {
23324
- const hostname = normalizeHostname(url.hostname);
23325
- const allowlist = (policy.allowPrivateHosts ?? []).map((entry) => normalizeHostname(entry.toLowerCase()));
23326
- if (allowlist.includes(hostname)) {
23327
- const version22 = isIP(hostname);
23328
- if (version22 === 4 || version22 === 6) {
23329
- return { hostname, addresses: [hostname] };
23330
- }
23331
- const lookup2 = policy.lookup ?? defaultTargetLookup;
23332
- let resolved2;
23333
- try {
23334
- resolved2 = await lookup2(hostname);
23335
- } catch {
23336
- throw new Error(`Webhook target ${hostname} could not be resolved`);
23337
- }
23338
- if (!Array.isArray(resolved2) || resolved2.length === 0) {
23339
- throw new Error(`Webhook target ${hostname} resolved to no addresses`);
23340
- }
23341
- const addresses = resolved2.map((entry) => normalizeHostname(entry.address));
23342
- return { hostname, addresses };
23343
- }
23344
- const version2 = isIP(hostname);
23345
- if (version2 === 4 || version2 === 6) {
23346
- if (isPrivateAddress(hostname)) {
23347
- throw new Error(`Webhook target ${hostname} is a private or special-use address`);
23348
- }
23349
- return { hostname, addresses: [hostname] };
23350
- }
23351
- const lookup = policy.lookup ?? defaultTargetLookup;
23352
- let resolved;
23353
- try {
23354
- resolved = await lookup(hostname);
23355
- } catch {
23356
- throw new Error(`Webhook target ${hostname} could not be resolved`);
23357
- }
23358
- if (!Array.isArray(resolved) || resolved.length === 0) {
23359
- throw new Error(`Webhook target ${hostname} resolved to no addresses`);
23360
- }
23361
- const allowed = [];
23362
- for (const entry of resolved) {
23363
- const address = normalizeHostname(entry.address);
23364
- if (isPrivateAddress(address)) {
23365
- if (allowlist.includes(address)) {
23366
- allowed.push(address);
23367
- continue;
23368
- }
23369
- throw new Error(`Webhook target ${hostname} resolves to private or special-use address ${address}`);
23370
- }
23371
- allowed.push(address);
23372
- }
23373
- if (allowed.length === 0) {
23374
- throw new Error(`Webhook target ${hostname} resolved to no public addresses`);
23375
- }
23376
- return { hostname, addresses: allowed };
23377
- }
23378
- function normalizeMaxRedirects(value) {
23379
- if (value === undefined)
23380
- return DEFAULT_MAX_REDIRECTS;
23381
- if (!Number.isInteger(value) || value < 0)
23382
- throw new Error("webhookTargetPolicy.maxRedirects must be a non-negative integer");
23383
- return value;
23384
- }
23385
- function normalizeHostname(hostname) {
23386
- const lower = hostname.toLowerCase();
23387
- if (lower.startsWith("[") && lower.endsWith("]"))
23388
- return lower.slice(1, -1);
23389
- return lower;
23390
- }
23391
- function stripZoneId(address) {
23392
- const percent = address.indexOf("%");
23393
- return percent === -1 ? address : address.slice(0, percent);
23394
- }
23395
- function ipv4ToInt(address) {
23396
- const parts = address.split(".");
23397
- if (parts.length !== 4)
23398
- return;
23399
- let value = 0;
23400
- for (const part of parts) {
23401
- if (!/^\d{1,3}$/.test(part))
23402
- return;
23403
- const octet = Number(part);
23404
- if (octet > 255)
23405
- return;
23406
- value = value << 8 | octet;
23407
- }
23408
- return value >>> 0;
23409
- }
23410
- function ipv4IntToString(integer) {
23411
- return [
23412
- integer >>> 24 & 255,
23413
- integer >>> 16 & 255,
23414
- integer >>> 8 & 255,
23415
- integer & 255
23416
- ].join(".");
23417
- }
23418
- function ipv6Groups(address) {
23419
- const raw = stripZoneId(address);
23420
- const doubleColon = raw.indexOf("::");
23421
- const headText = doubleColon === -1 ? raw : raw.slice(0, doubleColon);
23422
- const tailText = doubleColon === -1 ? "" : raw.slice(doubleColon + 2);
23423
- const parseGroups = (text) => {
23424
- if (text === "")
23425
- return [];
23426
- const out = [];
23427
- for (const part of text.split(":")) {
23428
- if (part.includes(".")) {
23429
- const v4 = ipv4ToInt(part);
23430
- if (v4 === undefined)
23431
- return;
23432
- out.push(v4 >>> 16 & 65535, v4 & 65535);
23433
- } else {
23434
- if (!/^[0-9a-fA-F]{1,4}$/.test(part))
23435
- return;
23436
- out.push(parseInt(part, 16));
23437
- }
23438
- }
23439
- return out;
23440
- };
23441
- const head = parseGroups(headText);
23442
- if (!head)
23443
- return;
23444
- const tail = parseGroups(tailText);
23445
- if (!tail)
23446
- return;
23447
- const total = head.length + tail.length;
23448
- if (doubleColon === -1) {
23449
- return total === 8 ? head : undefined;
23450
- }
23451
- if (total >= 8)
23452
- return;
23453
- return [...head, ...new Array(8 - total).fill(0), ...tail];
23454
- }
23455
- function ipv6MatchesPrefix(groups, prefixGroups, prefixBits) {
23456
- let remaining = prefixBits;
23457
- for (let index = 0;index < prefixGroups.length && remaining > 0; index += 1) {
23458
- const take = Math.min(16, remaining);
23459
- const mask = 65535 << 16 - take & 65535;
23460
- if ((groups[index] & mask) !== (prefixGroups[index] & mask))
23461
- return false;
23462
- remaining -= take;
23463
- }
23464
- return true;
23465
- }
23466
23291
  function now() {
23467
23292
  return new Date().toISOString();
23468
23293
  }
@@ -23493,18 +23318,9 @@ function buildWebhookRequest(event, channel, options = {}) {
23493
23318
  }
23494
23319
  return { body, headers };
23495
23320
  }
23496
- function normalizeWebhookUrl(raw) {
23497
- const url = new URL(raw);
23498
- if (url.username !== "" || url.password !== "") {
23499
- url.username = "";
23500
- url.password = "";
23501
- }
23502
- return url.toString();
23503
- }
23504
23321
  async function dispatchWebhook(event, channel, options = {}) {
23505
23322
  if (!channel.webhook)
23506
23323
  throw new Error(`Channel ${channel.id} has no webhook config`);
23507
- const webhookUrl = normalizeWebhookUrl(channel.webhook.url);
23508
23324
  const startedAt = now();
23509
23325
  let secret = channel.webhook.secret;
23510
23326
  if (channel.webhook.secretRef) {
@@ -23521,14 +23337,10 @@ async function dispatchWebhook(event, channel, options = {}) {
23521
23337
  }
23522
23338
  const timestamp = (options.now?.() ?? new Date).toISOString();
23523
23339
  const { body, headers } = buildWebhookRequest(event, channel, { secret, timestamp });
23524
- const validateTargets = options.webhookTargetPolicy !== undefined || options.fetchImpl === undefined;
23525
- if (validateTargets) {
23526
- return dispatchValidatedWebhook(event, channel, { body, headers, startedAt, options });
23527
- }
23528
23340
  const controller = new AbortController;
23529
23341
  const timeout = setTimeout(() => controller.abort(), channel.webhook.timeoutMs ?? 15000);
23530
23342
  try {
23531
- const response = await (options.fetchImpl ?? fetch)(webhookUrl, {
23343
+ const response = await (options.fetchImpl ?? fetch)(channel.webhook.url, {
23532
23344
  method: "POST",
23533
23345
  headers,
23534
23346
  body,
@@ -23556,130 +23368,6 @@ async function dispatchWebhook(event, channel, options = {}) {
23556
23368
  clearTimeout(timeout);
23557
23369
  }
23558
23370
  }
23559
- function isRedirectStatus(status) {
23560
- return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
23561
- }
23562
- function redirectKeepsBody(status) {
23563
- return status === 307 || status === 308;
23564
- }
23565
- async function pinnedNativeRequest(target, addresses, method, headers, body, signal, tls) {
23566
- const isHttps = target.protocol === "https:";
23567
- if (!isHttps && target.protocol !== "http:") {
23568
- throw new Error(`Webhook target uses unsupported protocol ${target.protocol}`);
23569
- }
23570
- const defaultPort = isHttps ? 443 : 80;
23571
- const port = target.port ? Number(target.port) : defaultPort;
23572
- const requestOptions = {
23573
- hostname: target.hostname,
23574
- port,
23575
- path: `${target.pathname}${target.search}`,
23576
- method,
23577
- headers,
23578
- ...tls?.ca ? { ca: tls.ca } : {},
23579
- lookup: (hostname, _options, callback) => {
23580
- const entries = addresses.map((address) => ({
23581
- address,
23582
- family: address.includes(":") ? 6 : 4
23583
- }));
23584
- callback(null, entries);
23585
- }
23586
- };
23587
- return new Promise((resolve2, reject) => {
23588
- const request = isHttps ? nodeHttpsRequest(requestOptions, onResponse) : nodeHttpRequest(requestOptions, onResponse);
23589
- const onAbort = () => {
23590
- const error = new Error("The operation was aborted.");
23591
- error.name = "AbortError";
23592
- request.destroy(error);
23593
- };
23594
- if (signal.aborted)
23595
- onAbort();
23596
- else
23597
- signal.addEventListener("abort", onAbort, { once: true });
23598
- request.on("error", reject);
23599
- if (body !== undefined)
23600
- request.write(body);
23601
- request.end();
23602
- function onResponse(response) {
23603
- const chunks = [];
23604
- response.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
23605
- response.on("error", reject);
23606
- response.on("end", () => {
23607
- const headersRecord = {};
23608
- for (const [name, value] of Object.entries(response.headers)) {
23609
- if (typeof value === "string")
23610
- headersRecord[name] = value;
23611
- else if (Array.isArray(value))
23612
- headersRecord[name] = value.join(", ");
23613
- }
23614
- resolve2(new Response(Buffer.concat(chunks), { status: response.statusCode ?? 200, headers: headersRecord }));
23615
- });
23616
- }
23617
- });
23618
- }
23619
- async function dispatchValidatedWebhook(event, channel, input) {
23620
- const { body, headers, startedAt, options } = input;
23621
- const webhook = channel.webhook;
23622
- if (!webhook)
23623
- throw new Error(`Channel ${channel.id} has no webhook config`);
23624
- const policy = options.webhookTargetPolicy ?? {};
23625
- const maxRedirects = normalizeMaxRedirects(policy.maxRedirects);
23626
- const controller = new AbortController;
23627
- const timeout = setTimeout(() => controller.abort(), webhook.timeoutMs ?? 15000);
23628
- try {
23629
- let target = new URL(normalizeWebhookUrl(webhook.url));
23630
- let requestHeaders = headers;
23631
- let method = "POST";
23632
- let requestBody = body;
23633
- let redirectsFollowed = 0;
23634
- for (;; ) {
23635
- const resolved = await resolveWebhookTarget(target, policy).catch((error) => {
23636
- throw new Error(`Webhook target rejected by SSRF guard: ${error.message}`);
23637
- });
23638
- const response = options.fetchImpl ? await options.fetchImpl(target, {
23639
- method,
23640
- headers: requestHeaders,
23641
- body: requestBody,
23642
- signal: controller.signal,
23643
- redirect: "manual"
23644
- }) : await pinnedNativeRequest(target, resolved.addresses, method, requestHeaders, requestBody, controller.signal, options.tls);
23645
- const location = response.headers.get("location");
23646
- if (isRedirectStatus(response.status) && location) {
23647
- if (redirectsFollowed >= maxRedirects) {
23648
- return failedAttempt(startedAt, `Webhook target exceeded ${maxRedirects} redirects`);
23649
- }
23650
- redirectsFollowed += 1;
23651
- const next = new URL(location, target);
23652
- target = next;
23653
- if (!redirectKeepsBody(response.status)) {
23654
- method = "GET";
23655
- requestBody = undefined;
23656
- requestHeaders = Object.fromEntries(Object.entries(requestHeaders).filter(([name]) => name.toLowerCase() !== "content-type" && name.toLowerCase() !== "content-length"));
23657
- }
23658
- continue;
23659
- }
23660
- const responseBody = truncate(await response.text());
23661
- return {
23662
- attempt: 1,
23663
- status: response.ok ? "success" : "failed",
23664
- startedAt,
23665
- completedAt: now(),
23666
- responseStatus: response.status,
23667
- responseBody,
23668
- error: response.ok ? undefined : `Webhook returned HTTP ${response.status}`
23669
- };
23670
- }
23671
- } catch (error) {
23672
- return {
23673
- attempt: 1,
23674
- status: "failed",
23675
- startedAt,
23676
- completedAt: now(),
23677
- error: error instanceof Error ? error.message : String(error)
23678
- };
23679
- } finally {
23680
- clearTimeout(timeout);
23681
- }
23682
- }
23683
23371
  function failedAttempt(startedAt, error) {
23684
23372
  return {
23685
23373
  attempt: 1,
@@ -23708,7 +23396,7 @@ async function dispatchCommand(event, channel) {
23708
23396
  HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
23709
23397
  HASNA_EVENT_JSON: eventJson
23710
23398
  };
23711
- return new Promise((resolve2) => {
23399
+ return new Promise((resolve3) => {
23712
23400
  const child = spawn(channel.command.command, channel.command.args ?? [], {
23713
23401
  cwd: channel.command.cwd,
23714
23402
  env,
@@ -23726,7 +23414,7 @@ async function dispatchCommand(event, channel) {
23726
23414
  });
23727
23415
  child.on("error", (error) => {
23728
23416
  clearTimeout(timeout);
23729
- resolve2({
23417
+ resolve3({
23730
23418
  attempt: 1,
23731
23419
  status: "failed",
23732
23420
  startedAt,
@@ -23739,7 +23427,7 @@ async function dispatchCommand(event, channel) {
23739
23427
  child.on("close", (code, signal) => {
23740
23428
  clearTimeout(timeout);
23741
23429
  const success = code === 0;
23742
- resolve2({
23430
+ resolve3({
23743
23431
  attempt: 1,
23744
23432
  status: success ? "success" : "failed",
23745
23433
  startedAt,
@@ -23875,9 +23563,7 @@ class EventsClient {
23875
23563
  this.transportOptions = {
23876
23564
  fetchImpl: options.fetchImpl,
23877
23565
  secretResolver: options.secretResolver,
23878
- now: options.now,
23879
- tls: options.tls,
23880
- webhookTargetPolicy: options.webhookTargetPolicy
23566
+ now: options.now
23881
23567
  };
23882
23568
  this.catalog = options.catalog ?? defaultEventTypeCatalog;
23883
23569
  this.validateCatalogTypes = options.validateCatalogTypes ?? false;
@@ -24082,44 +23768,9 @@ function normalizeRetryPolicy(policy) {
24082
23768
  multiplier: Math.max(1, policy?.multiplier ?? 2)
24083
23769
  };
24084
23770
  }
24085
- var HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR", HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME", LOCAL_JSON_EVENT_CURSOR_PREFIX = "local-json-v1:", DEFAULT_EVENT_PAGE_LIMIT = 100, MAX_EVENT_PAGE_LIMIT = 1000, DEFAULT_SIGNATURE_TOLERANCE_MS, DEFAULT_MAX_REDIRECTS = 5, IPV4_PRIVATE_RANGES, IPV6_SPECIAL_PREFIXES, defaultTargetLookup = async (hostname) => {
24086
- return dnsLookup(hostname, { all: true, verbatim: false });
24087
- }, EventValidationError, defaultEventTypeCatalog, APP_EVENT_V1_MAX_DATA_BYTES;
23771
+ var HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR", HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME", LOCAL_JSON_EVENT_CURSOR_PREFIX = "local-json-v1:", DEFAULT_EVENT_PAGE_LIMIT = 100, MAX_EVENT_PAGE_LIMIT = 1000, DEFAULT_SIGNATURE_TOLERANCE_MS, EventValidationError, defaultEventTypeCatalog, APP_EVENT_V1_MAX_DATA_BYTES;
24088
23772
  var init_dist = __esm(() => {
24089
23773
  DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
24090
- IPV4_PRIVATE_RANGES = [
24091
- [0, 16777215],
24092
- [167772160, 184549375],
24093
- [1681915904, 1686110207],
24094
- [2130706432, 2147483647],
24095
- [2851995648, 2852061183],
24096
- [2886729728, 2887778303],
24097
- [3221225472, 3221225727],
24098
- [3221225984, 3221226239],
24099
- [3227017984, 3227018239],
24100
- [3232235520, 3232301055],
24101
- [3323068416, 3323199487],
24102
- [3325256704, 3325256959],
24103
- [3405803776, 3405804031],
24104
- [3758096384, 4294967295]
24105
- ];
24106
- IPV6_SPECIAL_PREFIXES = [
24107
- { groups: [0, 0, 0, 0, 0, 0, 0, 0], bits: 128 },
24108
- { groups: [0, 0, 0, 0, 0, 0, 0, 1], bits: 128 },
24109
- { groups: [0, 0, 0, 0, 0, 65535, 0, 0], bits: 96 },
24110
- { groups: [100, 65435, 0, 0, 0, 0, 0, 0], bits: 96 },
24111
- { groups: [256, 0, 0, 0, 0, 0, 0, 0], bits: 64 },
24112
- { groups: [8193, 0, 0, 0, 0, 0, 0, 0], bits: 32 },
24113
- { groups: [8193, 2, 0, 0, 0, 0, 0, 0], bits: 48 },
24114
- { groups: [8193, 16, 0, 0, 0, 0, 0, 0], bits: 28 },
24115
- { groups: [8193, 3512, 0, 0, 0, 0, 0, 0], bits: 32 },
24116
- { groups: [8194, 0, 0, 0, 0, 0, 0, 0], bits: 16 },
24117
- { groups: [16383, 0, 0, 0, 0, 0, 0, 0], bits: 20 },
24118
- { groups: [64512, 0, 0, 0, 0, 0, 0, 0], bits: 7 },
24119
- { groups: [65152, 0, 0, 0, 0, 0, 0, 0], bits: 10 },
24120
- { groups: [65216, 0, 0, 0, 0, 0, 0, 0], bits: 10 },
24121
- { groups: [65280, 0, 0, 0, 0, 0, 0, 0], bits: 8 }
24122
- ];
24123
23774
  EventValidationError = class EventValidationError extends Error {
24124
23775
  eventType;
24125
23776
  issues;
@@ -24154,6 +23805,128 @@ var cachedClient;
24154
23805
  var init_event_sink = __esm(() => {
24155
23806
  init_dist();
24156
23807
  });
23808
+ // package.json
23809
+ var package_default = {
23810
+ name: "@hasna/skills",
23811
+ version: "0.1.72",
23812
+ description: "Skills library for AI coding agents",
23813
+ type: "module",
23814
+ bin: {
23815
+ skills: "bin/index.js",
23816
+ "skills-mcp": "bin/mcp.js",
23817
+ "skills-server": "bin/server.js",
23818
+ "skills-worker": "bin/worker.js",
23819
+ "skills-migrate": "bin/migrate.js"
23820
+ },
23821
+ exports: {
23822
+ ".": {
23823
+ import: "./dist/index.js",
23824
+ types: "./dist/index.d.ts"
23825
+ },
23826
+ "./storage": {
23827
+ import: "./dist/storage.js",
23828
+ types: "./dist/storage.d.ts"
23829
+ },
23830
+ "./sdk": {
23831
+ import: "./dist/sdk/index.js",
23832
+ types: "./dist/sdk/index.d.ts"
23833
+ },
23834
+ "./admin-contract": {
23835
+ import: "./dist/admin-contract.js",
23836
+ types: "./dist/admin-contract.d.ts"
23837
+ }
23838
+ },
23839
+ files: [
23840
+ "dist/",
23841
+ "!dist/**/*.test.d.ts",
23842
+ "!dist/test-preload.d.ts",
23843
+ "!dist/platform",
23844
+ "bin/",
23845
+ "migrations/",
23846
+ "docs/skill-standard.md",
23847
+ "schemas/",
23848
+ "LICENSE",
23849
+ "README.md"
23850
+ ],
23851
+ main: "./dist/index.js",
23852
+ types: "./dist/index.d.ts",
23853
+ scripts: {
23854
+ clean: "rm -rf bin/ dist/",
23855
+ build: "bun run clean && bun build ./src/cli/index.tsx --outdir ./bin --target bun && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/server/index.ts --outfile ./bin/server.js --target bun && bun build ./src/server/worker.ts --outfile ./bin/worker.js --target bun && bun build ./src/server/migrate.ts --outfile ./bin/migrate.js --target bun && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
23856
+ "build:js": "rm -rf dist && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
23857
+ test: "bun test --timeout 30000",
23858
+ dev: "bun run ./src/cli/index.tsx",
23859
+ "dev:watch": "bun --watch run ./src/cli/index.tsx",
23860
+ "dev:mcp": "bun --watch run ./src/mcp/index.ts",
23861
+ "dev:server": "bun --watch run ./src/server/index.ts",
23862
+ "dev:worker": "bun --watch run ./src/server/worker.ts",
23863
+ "docker:check": "bash scripts/docker-build-check.sh",
23864
+ migrate: "bun run ./src/server/migrate.ts",
23865
+ typecheck: "tsc --noEmit",
23866
+ "verify:release": "bun run scripts/release-guard.ts",
23867
+ prepare: "bun run build:js",
23868
+ prepack: "bun run build && bun run verify:release",
23869
+ prepublishOnly: "bun run typecheck && bun run test",
23870
+ postinstall: "mkdir -p $HOME/.hasna/skills/custom 2>/dev/null || true"
23871
+ },
23872
+ keywords: [
23873
+ "skills",
23874
+ "ai",
23875
+ "agent",
23876
+ "cli",
23877
+ "typescript",
23878
+ "bun",
23879
+ "claude",
23880
+ "codex",
23881
+ "gemini",
23882
+ "mcp",
23883
+ "model-context-protocol",
23884
+ "open-source",
23885
+ "skills-library",
23886
+ "automation"
23887
+ ],
23888
+ author: "Hasna",
23889
+ license: "Apache-2.0",
23890
+ devDependencies: {
23891
+ "@types/bun": "latest",
23892
+ "@types/node": "25.2.3",
23893
+ "@types/react": "^18.2.0",
23894
+ "bun-types": "1.3.14",
23895
+ "react-devtools-core": "^7.0.1",
23896
+ typescript: "^5",
23897
+ yaml: "^2.9.0"
23898
+ },
23899
+ dependencies: {
23900
+ "@aws-sdk/client-ecs": "^3.1079.0",
23901
+ "@aws-sdk/client-s3": "^3.1079.0",
23902
+ "@hasna/events": "0.1.16",
23903
+ "@hasna/paths": "0.1.0",
23904
+ "@modelcontextprotocol/sdk": "^1.26.0",
23905
+ chalk: "^5.3.0",
23906
+ commander: "^12.1.0",
23907
+ ink: "^5.0.1",
23908
+ "ink-select-input": "^6.0.0",
23909
+ "ink-spinner": "^5.0.0",
23910
+ "ink-text-input": "^6.0.0",
23911
+ react: "^18.2.0",
23912
+ zod: "^4.3.6"
23913
+ },
23914
+ engines: {
23915
+ bun: ">=1.0.0"
23916
+ },
23917
+ publishConfig: {
23918
+ registry: "https://registry.npmjs.org",
23919
+ access: "public"
23920
+ },
23921
+ repository: {
23922
+ type: "git",
23923
+ url: "git+https://github.com/hasna/apps.git"
23924
+ },
23925
+ homepage: "https://github.com/hasna/skills",
23926
+ bugs: {
23927
+ url: "https://github.com/hasna/skills/issues"
23928
+ }
23929
+ };
24157
23930
 
24158
23931
  // src/lib/remote-run-contract.ts
24159
23932
  var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
@@ -33325,7 +33098,7 @@ var WriteGetObjectResponse$ = [
33325
33098
  class CreateSessionCommand extends command(_ep4, _mw0, "CreateSession", CreateSession$) {
33326
33099
  }
33327
33100
  // ../../node_modules/.bun/@aws-sdk+client-s3@3.1112.0/node_modules/@aws-sdk/client-s3/package.json
33328
- var package_default = {
33101
+ var package_default2 = {
33329
33102
  name: "@aws-sdk/client-s3",
33330
33103
  version: "3.1112.0",
33331
33104
  description: "AWS SDK for JavaScript S3 Client for Node.js, Browser and React Native",
@@ -33875,7 +33648,7 @@ var getRuntimeConfig3 = (config) => {
33875
33648
  authSchemePreference: config?.authSchemePreference ?? import_config28.loadConfig(import_httpAuthSchemes3.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig),
33876
33649
  bodyLengthChecker: config?.bodyLengthChecker ?? import_serde4.calculateBodyLength,
33877
33650
  credentialDefaultProvider: config?.credentialDefaultProvider ?? defaultProvider,
33878
- defaultUserAgentProvider: config?.defaultUserAgentProvider ?? import_client19.createDefaultUserAgentProvider({ serviceId: clientSharedValues.serviceId, clientVersion: package_default.version }),
33651
+ defaultUserAgentProvider: config?.defaultUserAgentProvider ?? import_client19.createDefaultUserAgentProvider({ serviceId: clientSharedValues.serviceId, clientVersion: package_default2.version }),
33879
33652
  disableS3ExpressSessionAuth: config?.disableS3ExpressSessionAuth ?? import_config28.loadConfig($NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS, loaderConfig),
33880
33653
  eventStreamSerdeProvider: config?.eventStreamSerdeProvider ?? import_event_streams.eventStreamSerdeProvider,
33881
33654
  maxAttempts: config?.maxAttempts ?? import_config28.loadConfig(import_retry3.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config),
@@ -34322,13 +34095,12 @@ import { mkdirSync as mkdirSync3 } from "fs";
34322
34095
  import { dirname as dirname5 } from "path";
34323
34096
 
34324
34097
  // src/server/database-url.ts
34325
- import { isAbsolute, join as join3 } from "path";
34098
+ import { isAbsolute, join as join5 } from "path";
34326
34099
  import { fileURLToPath } from "url";
34327
34100
 
34328
34101
  // src/lib/config.ts
34329
- import { existsSync, readFileSync as readFileSync2, writeFileSync, mkdirSync, copyFileSync, readdirSync, statSync } from "fs";
34330
- import { join as join2, dirname as dirname2 } from "path";
34331
- import { homedir as homedir2 } from "os";
34102
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync, copyFileSync, readdirSync, statSync } from "fs";
34103
+ import { join as join4, dirname as dirname2 } from "path";
34332
34104
 
34333
34105
  // src/lib/retired-settings.ts
34334
34106
  var RETIRED_ENV_SUFFIXES = ["_STORAGE_MODE", "_DEPLOYMENT_MODE", "_CLOUD_MODE"];
@@ -34376,6 +34148,123 @@ function assertNoRetiredConfigKeys(config, source) {
34376
34148
  }
34377
34149
  }
34378
34150
 
34151
+ // src/lib/app-home.ts
34152
+ import { existsSync } from "fs";
34153
+ import { homedir as homedir3 } from "os";
34154
+ import { join as join3, resolve } from "path";
34155
+
34156
+ // ../../node_modules/.bun/@hasna+paths@0.1.0/node_modules/@hasna/paths/dist/index.js
34157
+ import { homedir as homedir2 } from "os";
34158
+ import { join as join2 } from "path";
34159
+ var KIND_ENV = {
34160
+ config: "HASNA_CONFIG_HOME",
34161
+ data: "HASNA_DATA_HOME",
34162
+ state: "HASNA_STATE_HOME",
34163
+ cache: "HASNA_CACHE_HOME"
34164
+ };
34165
+ var APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
34166
+ function assertApp(app) {
34167
+ if (typeof app !== "string" || app.length === 0) {
34168
+ throw new TypeError("paths: app must be a non-empty string");
34169
+ }
34170
+ if (!APP_SLUG_RE.test(app)) {
34171
+ throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
34172
+ }
34173
+ }
34174
+ function envOf(options) {
34175
+ return options.env ?? process.env;
34176
+ }
34177
+ function envValue(options, kind) {
34178
+ const value = envOf(options)[KIND_ENV[kind]];
34179
+ return typeof value === "string" && value.length > 0 ? value : undefined;
34180
+ }
34181
+ function isMacOS(platform) {
34182
+ return platform === "darwin";
34183
+ }
34184
+ function baseDir(kind, options) {
34185
+ const override = envValue(options, kind);
34186
+ if (override)
34187
+ return override;
34188
+ const home = options.home ?? homedir2();
34189
+ const platform = options.platform ?? process.platform;
34190
+ if (isMacOS(platform)) {
34191
+ switch (kind) {
34192
+ case "config":
34193
+ case "data":
34194
+ return join2(home, "Library", "Application Support", "Hasna");
34195
+ case "cache":
34196
+ return join2(home, "Library", "Caches", "Hasna");
34197
+ case "state":
34198
+ return join2(home, "Library", "Logs", "Hasna");
34199
+ }
34200
+ }
34201
+ switch (kind) {
34202
+ case "config":
34203
+ return join2(home, ".config", "hasna");
34204
+ case "data":
34205
+ return join2(home, ".local", "share", "hasna");
34206
+ case "state":
34207
+ return join2(home, ".local", "state", "hasna");
34208
+ case "cache":
34209
+ return join2(home, ".cache", "hasna");
34210
+ }
34211
+ }
34212
+ function resolvePath(kind, options) {
34213
+ assertApp(options.app);
34214
+ const appSegment = options.internal === true ? join2("internal", options.app) : options.app;
34215
+ return join2(baseDir(kind, options), appSegment);
34216
+ }
34217
+ function dataDir(options) {
34218
+ return resolvePath("data", options);
34219
+ }
34220
+
34221
+ // src/lib/app-home.ts
34222
+ var DATA_DIR_ENV = "HASNA_SKILLS_DIR";
34223
+ var HASNA_SKILLS_HOME_ENV = "HASNA_SKILLS_HOME";
34224
+ var SKILLS_HOME_ENV = "SKILLS_HOME";
34225
+ var DEFAULT_SQLITE_FILENAME = "server.db";
34226
+ var GLOBAL_CONFIG_FILENAME = "config.json";
34227
+ function effectiveHome() {
34228
+ return process.env["HOME"] || process.env["USERPROFILE"] || homedir3() || "/tmp";
34229
+ }
34230
+ function legacyDataRoot() {
34231
+ return join3(effectiveHome(), ".hasna", "skills");
34232
+ }
34233
+ function resolverDataRoot(home = effectiveHome()) {
34234
+ return dataDir({ app: "skills", home });
34235
+ }
34236
+ function adoptResolverDataRoot(resolved, env = process.env) {
34237
+ const dataOverride = env.HASNA_DATA_HOME;
34238
+ if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
34239
+ return true;
34240
+ return existsSync(join3(resolved, DEFAULT_SQLITE_FILENAME)) || existsSync(join3(resolved, GLOBAL_CONFIG_FILENAME));
34241
+ }
34242
+ function exactDataRoot() {
34243
+ for (const key of [DATA_DIR_ENV, HASNA_SKILLS_HOME_ENV, SKILLS_HOME_ENV]) {
34244
+ const dir = process.env[key]?.trim();
34245
+ if (dir)
34246
+ return resolve(dir);
34247
+ }
34248
+ return;
34249
+ }
34250
+ function hasExactOverride(env = process.env) {
34251
+ return Boolean(env[DATA_DIR_ENV]?.trim()) || Boolean(env[HASNA_SKILLS_HOME_ENV]?.trim()) || Boolean(env[SKILLS_HOME_ENV]?.trim());
34252
+ }
34253
+ function hasOperatorOverride(env = process.env) {
34254
+ return hasExactOverride(env) || Boolean(env.HASNA_DATA_HOME?.trim());
34255
+ }
34256
+ function getDataRoot() {
34257
+ const exact = exactDataRoot();
34258
+ if (exact)
34259
+ return exact;
34260
+ const resolved = resolverDataRoot();
34261
+ return adoptResolverDataRoot(resolved) ? resolve(resolved) : resolve(legacyDataRoot());
34262
+ }
34263
+ function skillsDataRootForHome(home) {
34264
+ const resolved = resolverDataRoot(home);
34265
+ return adoptResolverDataRoot(resolved) ? resolve(resolved) : resolve(join3(home, ".hasna", "skills"));
34266
+ }
34267
+
34379
34268
  // src/lib/config.ts
34380
34269
  var ENUM_KEYS = {
34381
34270
  defaultAgent: ["claude", "codex", "gemini", "pi", "opencode", "all"],
@@ -34390,19 +34279,19 @@ function allowedValues(key) {
34390
34279
  return ENUM_KEYS[key];
34391
34280
  }
34392
34281
  function mergeDirectoryContents(sourceDir, targetDir) {
34393
- if (!existsSync(sourceDir))
34282
+ if (!existsSync2(sourceDir))
34394
34283
  return;
34395
34284
  mkdirSync(targetDir, { recursive: true });
34396
34285
  for (const entry of readdirSync(sourceDir)) {
34397
- const sourcePath = join2(sourceDir, entry);
34398
- const targetPath = join2(targetDir, entry);
34286
+ const sourcePath = join4(sourceDir, entry);
34287
+ const targetPath = join4(targetDir, entry);
34399
34288
  try {
34400
34289
  const sourceStat = statSync(sourcePath);
34401
34290
  if (sourceStat.isDirectory()) {
34402
34291
  mergeDirectoryContents(sourcePath, targetPath);
34403
34292
  continue;
34404
34293
  }
34405
- if (!existsSync(targetPath))
34294
+ if (!existsSync2(targetPath))
34406
34295
  copyFileSync(sourcePath, targetPath);
34407
34296
  } catch {}
34408
34297
  }
@@ -34427,44 +34316,40 @@ function normalizeConfigValue(key, value) {
34427
34316
  return value.trim() ? value : undefined;
34428
34317
  return;
34429
34318
  }
34430
- var DATA_DIR_ENV = "HASNA_SKILLS_DIR";
34431
34319
  var INSTALLED_SKILLS_DIRNAME = "installed";
34432
34320
  var SKILLS_CACHE_DIRNAME = "skills";
34433
34321
  var LAYOUT_MIGRATION_RECORD = ".layout-migration.json";
34434
34322
  function isOwnerLayoutMigrated(appDir) {
34435
- return existsSync(join2(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD));
34323
+ return existsSync2(join4(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD));
34436
34324
  }
34437
34325
  function getDataDir() {
34438
- const override = process.env[DATA_DIR_ENV];
34439
- if (override) {
34440
- try {
34441
- mkdirSync(override, { recursive: true });
34442
- } catch {}
34443
- return override;
34444
- }
34445
- const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir2();
34446
- const newDir = join2(home, ".hasna", "skills");
34447
- const oldDir = join2(home, ".skills");
34448
- const oldConfigFile = join2(home, ".skillsrc");
34449
- mkdirSync(newDir, { recursive: true });
34326
+ const root3 = getDataRoot();
34450
34327
  try {
34451
- mergeDirectoryContents(oldDir, newDir);
34328
+ mkdirSync(root3, { recursive: true });
34452
34329
  } catch {}
34453
- if (existsSync(oldConfigFile) && !existsSync(join2(newDir, "config.json"))) {
34330
+ if (hasOperatorOverride())
34331
+ return root3;
34332
+ const home = effectiveHome();
34333
+ const oldDir = join4(home, ".skills");
34334
+ const oldConfigFile = join4(home, ".skillsrc");
34335
+ try {
34336
+ mergeDirectoryContents(oldDir, root3);
34337
+ } catch {}
34338
+ if (existsSync2(oldConfigFile) && !existsSync2(join4(root3, "config.json"))) {
34454
34339
  try {
34455
- copyFileSync(oldConfigFile, join2(newDir, "config.json"));
34340
+ copyFileSync(oldConfigFile, join4(root3, "config.json"));
34456
34341
  } catch {}
34457
34342
  }
34458
- return newDir;
34343
+ return root3;
34459
34344
  }
34460
34345
  function getConfigPath(scope) {
34461
34346
  if (scope === "global") {
34462
- return join2(getDataDir(), "config.json");
34347
+ return join4(getDataDir(), "config.json");
34463
34348
  }
34464
- return join2(process.cwd(), "skills.config.json");
34349
+ return join4(process.cwd(), "skills.config.json");
34465
34350
  }
34466
34351
  function readConfigFile(path) {
34467
- if (!existsSync(path))
34352
+ if (!existsSync2(path))
34468
34353
  return {};
34469
34354
  let parsed;
34470
34355
  try {
@@ -34500,7 +34385,7 @@ function saveConfig(key, value, scope = "project") {
34500
34385
  }
34501
34386
  const filePath = getConfigPath(scope);
34502
34387
  let existing = {};
34503
- if (existsSync(filePath)) {
34388
+ if (existsSync2(filePath)) {
34504
34389
  try {
34505
34390
  existing = JSON.parse(readFileSync2(filePath, "utf-8"));
34506
34391
  if (typeof existing !== "object" || existing === null || Array.isArray(existing)) {
@@ -34511,7 +34396,7 @@ function saveConfig(key, value, scope = "project") {
34511
34396
  }
34512
34397
  } else {
34513
34398
  const dir = dirname2(filePath);
34514
- if (!existsSync(dir)) {
34399
+ if (!existsSync2(dir)) {
34515
34400
  mkdirSync(dir, { recursive: true });
34516
34401
  }
34517
34402
  }
@@ -34525,7 +34410,7 @@ function unsetConfig(key, scope = "project") {
34525
34410
  throw new Error(`Unknown config key: ${key}. Valid keys: ${validKeys().join(", ")}`);
34526
34411
  }
34527
34412
  const filePath = getConfigPath(scope);
34528
- if (!existsSync(filePath))
34413
+ if (!existsSync2(filePath))
34529
34414
  return false;
34530
34415
  let existing;
34531
34416
  try {
@@ -34545,14 +34430,14 @@ function unsetConfig(key, scope = "project") {
34545
34430
  }
34546
34431
 
34547
34432
  // src/server/database-url.ts
34548
- var DEFAULT_SQLITE_FILENAME = "server.db";
34433
+ var DEFAULT_SQLITE_FILENAME2 = "server.db";
34549
34434
  var SQLITE_MEMORY_PATH = ":memory:";
34550
34435
  var POSTGRES_SCHEMES = new Set(["postgres", "postgresql"]);
34551
34436
  var SQLITE_SCHEMES = new Set(["sqlite", "sqlite3", "file"]);
34552
34437
  var MEMORY_SCHEMES = new Set(["memory"]);
34553
34438
  var SQLITE_EXTENSIONS = [".db", ".sqlite", ".sqlite3", ".db3"];
34554
34439
  function defaultSqlitePath() {
34555
- return join3(getDataDir(), DEFAULT_SQLITE_FILENAME);
34440
+ return join5(getDataDir(), DEFAULT_SQLITE_FILENAME2);
34556
34441
  }
34557
34442
  function resolveDatabaseTarget(raw) {
34558
34443
  const value = raw?.trim();
@@ -34579,7 +34464,7 @@ function resolveDatabaseTarget(raw) {
34579
34464
  throw new Error(`unsupported database scheme "${scheme}:". Supported: postgres://, postgresql://, sqlite:, file:, ` + `an absolute or relative path to a .db/.sqlite file, ":memory:", or "memory:" (non-durable, tests only). ` + `Leave the setting empty to use the default SQLite database at ${defaultSqlitePath()}.`);
34580
34465
  }
34581
34466
  if (looksLikeSqlitePath(value)) {
34582
- const path = isAbsolute(value) ? value : join3(process.cwd(), value);
34467
+ const path = isAbsolute(value) ? value : join5(process.cwd(), value);
34583
34468
  return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
34584
34469
  }
34585
34470
  throw new Error(`could not resolve a database backend from "${value}". Use postgres://\u2026, sqlite:\u2026, an absolute or ` + `relative path ending in ${SQLITE_EXTENSIONS.join("/")}, ":memory:", or leave it empty for the ` + `default SQLite database at ${defaultSqlitePath()}.`);
@@ -34603,7 +34488,7 @@ function sqlitePathFromUrl(value, scheme) {
34603
34488
  }
34604
34489
  return rest.slice(2).replace(/^\/\/+/, "/");
34605
34490
  }
34606
- return isAbsolute(rest) ? rest : join3(process.cwd(), rest);
34491
+ return isAbsolute(rest) ? rest : join5(process.cwd(), rest);
34607
34492
  }
34608
34493
  function looksLikeSqlitePath(value) {
34609
34494
  if (value.includes("/"))
@@ -34615,7 +34500,7 @@ function looksLikeSqlitePath(value) {
34615
34500
  import { Database } from "bun:sqlite";
34616
34501
  import { randomUUID as randomUUID2 } from "crypto";
34617
34502
  import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
34618
- import { dirname as dirname4, join as join5 } from "path";
34503
+ import { dirname as dirname4, join as join7 } from "path";
34619
34504
 
34620
34505
  // src/server/auth.ts
34621
34506
  import { createHash as createHash4 } from "crypto";
@@ -34648,16 +34533,16 @@ function publicPrincipal(partial = {}) {
34648
34533
  }
34649
34534
 
34650
34535
  // src/server/migrations-dir.ts
34651
- import { existsSync as existsSync2 } from "fs";
34652
- import { dirname as dirname3, join as join4 } from "path";
34536
+ import { existsSync as existsSync3 } from "fs";
34537
+ import { dirname as dirname3, join as join6 } from "path";
34653
34538
  var MIGRATION_DIALECTS = ["postgres", "sqlite"];
34654
34539
  var MAX_WALK_UP = 6;
34655
34540
  function findMigrationsRoot(startDirs = defaultStartDirs()) {
34656
34541
  for (const start of startDirs) {
34657
34542
  let dir = start;
34658
34543
  for (let level = 0;level < MAX_WALK_UP; level += 1) {
34659
- const candidate = join4(dir, "migrations");
34660
- if (MIGRATION_DIALECTS.some((dialect) => existsSync2(join4(candidate, dialect))))
34544
+ const candidate = join6(dir, "migrations");
34545
+ if (MIGRATION_DIALECTS.some((dialect) => existsSync3(join6(candidate, dialect))))
34661
34546
  return candidate;
34662
34547
  const parent = dirname3(dir);
34663
34548
  if (parent === dir)
@@ -34671,8 +34556,8 @@ function resolveMigrationsDir(dialect, root3 = findMigrationsRoot()) {
34671
34556
  if (!root3) {
34672
34557
  throw new Error(`could not locate the migrations directory for dialect "${dialect}". ` + `Expected a migrations/${dialect}/ folder alongside the package root.`);
34673
34558
  }
34674
- const dir = join4(root3, dialect);
34675
- if (!existsSync2(dir)) {
34559
+ const dir = join6(root3, dialect);
34560
+ if (!existsSync3(dir)) {
34676
34561
  throw new Error(`migrations directory not found: ${dir}`);
34677
34562
  }
34678
34563
  return dir;
@@ -35417,7 +35302,7 @@ function applySqliteMigrations(db, migrationsDir = resolveMigrationsDir("sqlite"
35417
35302
  const appliedNow = [];
35418
35303
  for (const file of files) {
35419
35304
  const version2 = file.replace(/\.sql$/, "");
35420
- const text = readFileSync3(join5(migrationsDir, file), "utf8");
35305
+ const text = readFileSync3(join7(migrationsDir, file), "utf8");
35421
35306
  const apply = db.transaction(() => {
35422
35307
  const already = db.query("SELECT 1 AS present FROM schema_migrations WHERE version = ? LIMIT 1").get(version2);
35423
35308
  if (already)
@@ -36887,17 +36772,17 @@ function mergeSkillRegistryLists(...groups) {
36887
36772
  }
36888
36773
 
36889
36774
  // src/server/registry.ts
36890
- import { existsSync as existsSync13, readFileSync as readFileSync13 } from "fs";
36891
- import { resolve, sep as sep2 } from "path";
36775
+ import { existsSync as existsSync14, readFileSync as readFileSync13 } from "fs";
36776
+ import { resolve as resolve2, sep as sep2 } from "path";
36892
36777
 
36893
36778
  // src/lib/registry.ts
36894
- import { existsSync as existsSync8, readFileSync as readFileSync8, readdirSync as readdirSync7 } from "fs";
36895
- import { join as join11 } from "path";
36779
+ import { existsSync as existsSync9, readFileSync as readFileSync8, readdirSync as readdirSync7 } from "fs";
36780
+ import { join as join13 } from "path";
36896
36781
 
36897
36782
  // src/lib/portable-skills.ts
36898
36783
  import {
36899
36784
  cpSync as cpSync2,
36900
- existsSync as existsSync7,
36785
+ existsSync as existsSync8,
36901
36786
  mkdirSync as mkdirSync5,
36902
36787
  mkdtempSync,
36903
36788
  readdirSync as readdirSync6,
@@ -36906,7 +36791,7 @@ import {
36906
36791
  statSync as statSync6,
36907
36792
  writeFileSync as writeFileSync3
36908
36793
  } from "fs";
36909
- import { basename as basename2, dirname as dirname7, isAbsolute as isAbsolute3, join as join10, normalize as normalize2 } from "path";
36794
+ import { basename as basename2, dirname as dirname7, isAbsolute as isAbsolute3, join as join12, normalize as normalize2 } from "path";
36910
36795
 
36911
36796
  // src/lib/registry-data/development-tools.ts
36912
36797
  var DEVELOPMENT_TOOLS_SKILLS = [
@@ -37626,8 +37511,8 @@ var SKILLS = [
37626
37511
  ];
37627
37512
 
37628
37513
  // src/lib/hosted-skill-set.ts
37629
- import { existsSync as existsSync3, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
37630
- import { join as join6 } from "path";
37514
+ import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
37515
+ import { join as join8 } from "path";
37631
37516
  var HOSTED_RUNTIMES = new Set(["hosted"]);
37632
37517
  var HOSTED_SOURCES = new Set(["remote", "private-hosted"]);
37633
37518
  function normalizeMarker(value) {
@@ -37640,8 +37525,8 @@ function isHostedMetadataPackage(pkg) {
37640
37525
  return HOSTED_RUNTIMES.has(normalizeMarker(skills.runtime)) || HOSTED_SOURCES.has(normalizeMarker(skills.source));
37641
37526
  }
37642
37527
  function isHostedMetadataSkillDir(skillDir) {
37643
- const pkgPath = join6(skillDir, "package.json");
37644
- if (!existsSync3(pkgPath))
37528
+ const pkgPath = join8(skillDir, "package.json");
37529
+ if (!existsSync4(pkgPath))
37645
37530
  return false;
37646
37531
  try {
37647
37532
  return isHostedMetadataPackage(JSON.parse(readFileSync4(pkgPath, "utf8")));
@@ -37665,8 +37550,8 @@ var BRACE_SOURCE_EXCLUSION = new RegExp(`^!skills/\\{(${SLUG}(?:,${SLUG})+)\\}/s
37665
37550
  var SINGLE_SOURCE_EXCLUSION = new RegExp(`^!skills/(${SLUG})/src$`);
37666
37551
 
37667
37552
  // src/lib/skill-validation.ts
37668
- import { existsSync as existsSync4, lstatSync, readFileSync as readFileSync5, readdirSync as readdirSync4, statSync as statSync3 } from "fs";
37669
- import { isAbsolute as isAbsolute2, join as join7, normalize } from "path";
37553
+ import { existsSync as existsSync5, lstatSync, readFileSync as readFileSync5, readdirSync as readdirSync4, statSync as statSync3 } from "fs";
37554
+ import { isAbsolute as isAbsolute2, join as join9, normalize } from "path";
37670
37555
  var VALID_SKILL_KINDS = ["executable", "instruction"];
37671
37556
  var DOC_FILES = ["SKILL.md", "README.md", "CLAUDE.md"];
37672
37557
  var RESERVED_SKILL_ENTRIES = new Set([
@@ -37804,7 +37689,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
37804
37689
  binCommands: [],
37805
37690
  docFiles: []
37806
37691
  };
37807
- if (!existsSync4(skillPath)) {
37692
+ if (!existsSync5(skillPath)) {
37808
37693
  add(issues, "skill.dir_missing", `Skill directory not found: ${skillPath}`);
37809
37694
  return {
37810
37695
  name: bareName,
@@ -37819,7 +37704,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
37819
37704
  add(issues, "skill.name_invalid", `Skill name '${bareName}' must use lowercase letters, numbers, dots, underscores, or hyphens`);
37820
37705
  }
37821
37706
  for (const entry of readdirSync4(skillPath).sort()) {
37822
- const entryPath = join7(skillPath, entry);
37707
+ const entryPath = join9(skillPath, entry);
37823
37708
  if (RESERVED_SKILL_ENTRIES.has(entry)) {
37824
37709
  add(issues, "skill.reserved_file", `Reserved file '${entry}' is not allowed in skill packages`);
37825
37710
  }
@@ -37831,14 +37716,14 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
37831
37716
  }
37832
37717
  }
37833
37718
  for (const docFile of DOC_FILES) {
37834
- if (existsSync4(join7(skillPath, docFile)))
37719
+ if (existsSync5(join9(skillPath, docFile)))
37835
37720
  metadata.docFiles.push(docFile);
37836
37721
  }
37837
37722
  if (metadata.docFiles.length === 0) {
37838
37723
  add(issues, "skill.docs_missing", "Missing documentation file: expected SKILL.md, README.md, or CLAUDE.md");
37839
37724
  }
37840
- const skillMdPath = join7(skillPath, "SKILL.md");
37841
- if (existsSync4(skillMdPath)) {
37725
+ const skillMdPath = join9(skillPath, "SKILL.md");
37726
+ if (existsSync5(skillMdPath)) {
37842
37727
  const frontmatter = parseSkillFrontmatter(readFileSync5(skillMdPath, "utf-8"));
37843
37728
  if (!frontmatter) {
37844
37729
  add(warnings, "skill.frontmatter_missing", "SKILL.md has no YAML frontmatter");
@@ -37881,8 +37766,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
37881
37766
  }
37882
37767
  metadata.kind = resolvedKind;
37883
37768
  const isInstruction = resolvedKind === "instruction";
37884
- const pkgPath = join7(skillPath, "package.json");
37885
- if (!existsSync4(pkgPath)) {
37769
+ const pkgPath = join9(skillPath, "package.json");
37770
+ if (!existsSync5(pkgPath)) {
37886
37771
  if (!isInstruction)
37887
37772
  add(issues, "package.missing", "Missing package.json");
37888
37773
  } else {
@@ -37940,8 +37825,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
37940
37825
  add(issues, "package.bin_target_unsafe", `package.json bin '${command3}' target '${target}' must stay inside the skill directory`);
37941
37826
  continue;
37942
37827
  }
37943
- const targetPath = join7(skillPath, target);
37944
- if (!existsSync4(targetPath)) {
37828
+ const targetPath = join9(skillPath, target);
37829
+ if (!existsSync5(targetPath)) {
37945
37830
  add(warnings, "package.bin_target_missing", `package.json bin '${command3}' target '${target}' is not present before build`);
37946
37831
  } else if (statSync3(targetPath).isDirectory()) {
37947
37832
  add(issues, "package.bin_target_directory", `package.json bin '${command3}' target '${target}' must point to a file, not a directory`);
@@ -37958,17 +37843,17 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
37958
37843
  metadata.runtime = "none";
37959
37844
  } else {
37960
37845
  metadata.runtime = hostedMetadata ? "hosted" : "local";
37961
- const srcDir = join7(skillPath, "src");
37846
+ const srcDir = join9(skillPath, "src");
37962
37847
  if (hostedMetadata) {
37963
- if (existsSync4(srcDir)) {
37848
+ if (existsSync5(srcDir)) {
37964
37849
  add(issues, "skill.hosted_source_forbidden", "Hosted metadata skills must not include local implementation source");
37965
37850
  }
37966
- } else if (!existsSync4(srcDir)) {
37851
+ } else if (!existsSync5(srcDir)) {
37967
37852
  add(issues, "skill.src_missing", "Missing src/ directory");
37968
- } else if (!existsSync4(join7(srcDir, "index.ts")) && !existsSync4(join7(srcDir, "index.js"))) {
37853
+ } else if (!existsSync5(join9(srcDir, "index.ts")) && !existsSync5(join9(srcDir, "index.js"))) {
37969
37854
  add(issues, "skill.src_index_missing", "Missing src/index.ts or src/index.js");
37970
37855
  } else {
37971
- const indexPath = existsSync4(join7(srcDir, "index.ts")) ? join7(srcDir, "index.ts") : join7(srcDir, "index.js");
37856
+ const indexPath = existsSync5(join9(srcDir, "index.ts")) ? join9(srcDir, "index.ts") : join9(srcDir, "index.js");
37972
37857
  const size = statSync3(indexPath).size;
37973
37858
  if (size < 50)
37974
37859
  add(warnings, "skill.src_index_minimal", `Source entry point is very small (${size}B)`);
@@ -37992,8 +37877,8 @@ function validateRegistryConsistency(registry, skillsDir) {
37992
37877
  seen.add(name);
37993
37878
  return false;
37994
37879
  })));
37995
- const skillDirs = existsSync4(skillsDir) ? readdirSync4(skillsDir).filter((entry) => {
37996
- const fullPath = join7(skillsDir, entry);
37880
+ const skillDirs = existsSync5(skillsDir) ? readdirSync4(skillsDir).filter((entry) => {
37881
+ const fullPath = join9(skillsDir, entry);
37997
37882
  return !entry.startsWith(".") && entry !== "_common" && statSync3(fullPath).isDirectory();
37998
37883
  }) : [];
37999
37884
  const directoryNames = new Set(skillDirs);
@@ -38010,8 +37895,8 @@ function validateRegistryConsistency(registry, skillsDir) {
38010
37895
 
38011
37896
  // src/lib/skill-hash.ts
38012
37897
  import { createHash as createHash7 } from "crypto";
38013
- import { existsSync as existsSync5, readdirSync as readdirSync5, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
38014
- import { join as join8, sep } from "path";
37898
+ import { existsSync as existsSync6, readdirSync as readdirSync5, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
37899
+ import { join as join10, sep } from "path";
38015
37900
  var CONTENT_HASH_ALGORITHM = "sha256";
38016
37901
  var HASH_EXCLUDE_DIRS = new Set([".git", "node_modules", "dist", "build", ".turbo"]);
38017
37902
  var HASH_COVERAGE = [
@@ -38070,8 +37955,8 @@ function collectBundleFiles(skillPath) {
38070
37955
  if (seen.has(entry))
38071
37956
  continue;
38072
37957
  seen.add(entry);
38073
- const absolute = join8(skillPath, entry);
38074
- if (!existsSync5(absolute))
37958
+ const absolute = join10(skillPath, entry);
37959
+ if (!existsSync6(absolute))
38075
37960
  continue;
38076
37961
  if (statSync4(absolute).isDirectory())
38077
37962
  collectDirectory(files, absolute, entry);
@@ -38084,7 +37969,7 @@ function collectDirectory(files, dir, rel) {
38084
37969
  for (const entry of readdirSync5(dir).sort()) {
38085
37970
  if (entry.startsWith("."))
38086
37971
  continue;
38087
- const absolute = join8(dir, entry);
37972
+ const absolute = join10(dir, entry);
38088
37973
  const childRel = `${rel}/${entry}`;
38089
37974
  let stats;
38090
37975
  try {
@@ -38304,14 +38189,14 @@ function validateRuntimeContract(manifest, issues, strict) {
38304
38189
  // src/lib/portable-skills-files.ts
38305
38190
  import {
38306
38191
  cpSync,
38307
- existsSync as existsSync6,
38192
+ existsSync as existsSync7,
38308
38193
  lstatSync as lstatSync2,
38309
38194
  mkdirSync as mkdirSync4,
38310
38195
  readFileSync as readFileSync7,
38311
38196
  realpathSync,
38312
38197
  writeFileSync as writeFileSync2
38313
38198
  } from "fs";
38314
- import { basename, dirname as dirname6, join as join9, relative } from "path";
38199
+ import { basename, dirname as dirname6, join as join11, relative } from "path";
38315
38200
  var ANY_SEGMENT_COPY_EXCLUDES = new Set([
38316
38201
  ".git",
38317
38202
  ".DS_Store",
@@ -38354,12 +38239,12 @@ function normalizePortableSkillName(name) {
38354
38239
  return normalized;
38355
38240
  }
38356
38241
  function readPortableSkillManifest(skillPath, fallbackName = basename(skillPath)) {
38357
- const skillJsonPath = join9(skillPath, "skill.json");
38358
- const skillMdPath = join9(skillPath, "SKILL.md");
38359
- const pkgPath = join9(skillPath, "package.json");
38360
- const jsonManifest = existsSync6(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
38361
- const frontmatter = existsSync6(skillMdPath) ? parseSkillFrontmatter(readFileSync7(skillMdPath, "utf-8")) ?? undefined : undefined;
38362
- const pkg = existsSync6(pkgPath) ? readJsonObject(pkgPath) : undefined;
38242
+ const skillJsonPath = join11(skillPath, "skill.json");
38243
+ const skillMdPath = join11(skillPath, "SKILL.md");
38244
+ const pkgPath = join11(skillPath, "package.json");
38245
+ const jsonManifest = existsSync7(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
38246
+ const frontmatter = existsSync7(skillMdPath) ? parseSkillFrontmatter(readFileSync7(skillMdPath, "utf-8")) ?? undefined : undefined;
38247
+ const pkg = existsSync7(pkgPath) ? readJsonObject(pkgPath) : undefined;
38363
38248
  const name = normalizePortableSkillName(stringField(jsonManifest, "name") ?? frontmatter?.name ?? stringValue(pkg?.name) ?? fallbackName);
38364
38249
  const description = stringField(jsonManifest, "description") ?? frontmatter?.description ?? stringValue(pkg?.description) ?? `${name} skill`;
38365
38250
  const version2 = stringField(jsonManifest, "version") ?? frontmatter?.version ?? stringValue(pkg?.version) ?? PORTABLE_SKILL_DEFAULT_VERSION;
@@ -38405,7 +38290,7 @@ function createInstructionManifest(name, options) {
38405
38290
  }
38406
38291
  function writeInstructionSkillTemplate(skillPath, manifest) {
38407
38292
  mkdirSync4(skillPath, { recursive: true });
38408
- writeFileSync2(join9(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
38293
+ writeFileSync2(join11(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
38409
38294
  writeSkillJsonWithHash(skillPath, manifest);
38410
38295
  }
38411
38296
  function renderInstructionSkillMd(manifest) {
@@ -38454,12 +38339,12 @@ function createPortableManifest(name, options) {
38454
38339
  };
38455
38340
  }
38456
38341
  function writePortableSkillTemplate(skillPath, manifest) {
38457
- mkdirSync4(join9(skillPath, "src"), { recursive: true });
38458
- writeFileSync2(join9(skillPath, "SKILL.md"), renderSkillMd(manifest));
38459
- writeFileSync2(join9(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
38460
- writeFileSync2(join9(skillPath, "package.json"), renderPackageJson(manifest));
38461
- writeFileSync2(join9(skillPath, "tsconfig.json"), renderTsconfig());
38462
- writeFileSync2(join9(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
38342
+ mkdirSync4(join11(skillPath, "src"), { recursive: true });
38343
+ writeFileSync2(join11(skillPath, "SKILL.md"), renderSkillMd(manifest));
38344
+ writeFileSync2(join11(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
38345
+ writeFileSync2(join11(skillPath, "package.json"), renderPackageJson(manifest));
38346
+ writeFileSync2(join11(skillPath, "tsconfig.json"), renderTsconfig());
38347
+ writeFileSync2(join11(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
38463
38348
  writeSkillJsonWithHash(skillPath, manifest);
38464
38349
  }
38465
38350
  function fillContractDefaults(manifest, entrypoint) {
@@ -38484,7 +38369,7 @@ function writeSkillJsonWithHash(skillPath, manifest) {
38484
38369
  content_hash: undefined
38485
38370
  }
38486
38371
  };
38487
- writeFileSync2(join9(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
38372
+ writeFileSync2(join11(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
38488
38373
  `);
38489
38374
  const hash = computeContentHash(skillPath);
38490
38375
  const withHash = {
@@ -38494,13 +38379,13 @@ function writeSkillJsonWithHash(skillPath, manifest) {
38494
38379
  content_hash: hash
38495
38380
  }
38496
38381
  };
38497
- writeFileSync2(join9(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
38382
+ writeFileSync2(join11(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
38498
38383
  `);
38499
38384
  return withHash;
38500
38385
  }
38501
38386
  function readExistingSkillJson(skillPath) {
38502
- const path = join9(skillPath, "skill.json");
38503
- if (!existsSync6(path))
38387
+ const path = join11(skillPath, "skill.json");
38388
+ if (!existsSync7(path))
38504
38389
  return {};
38505
38390
  try {
38506
38391
  const parsed = JSON.parse(readFileSync7(path, "utf-8"));
@@ -38533,28 +38418,28 @@ function ensurePortableSkillFiles(skillPath, manifest) {
38533
38418
  tags: next.tags?.length ? next.tags : ["custom", next.name]
38534
38419
  };
38535
38420
  const entry = next.commands[0]?.entry ?? "src/index.ts";
38536
- if (entry && !existsSync6(join9(skillPath, entry))) {
38537
- mkdirSync4(dirname6(join9(skillPath, entry)), { recursive: true });
38538
- writeFileSync2(join9(skillPath, entry), renderEntrypoint(next));
38421
+ if (entry && !existsSync7(join11(skillPath, entry))) {
38422
+ mkdirSync4(dirname6(join11(skillPath, entry)), { recursive: true });
38423
+ writeFileSync2(join11(skillPath, entry), renderEntrypoint(next));
38539
38424
  }
38540
- if (!existsSync6(join9(skillPath, "SKILL.md")))
38541
- writeFileSync2(join9(skillPath, "SKILL.md"), renderSkillMd(next));
38425
+ if (!existsSync7(join11(skillPath, "SKILL.md")))
38426
+ writeFileSync2(join11(skillPath, "SKILL.md"), renderSkillMd(next));
38542
38427
  else
38543
- writeFileSync2(join9(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync7(join9(skillPath, "SKILL.md"), "utf-8"), next));
38544
- if (!existsSync6(join9(skillPath, "AGENTS.md")))
38545
- writeFileSync2(join9(skillPath, "AGENTS.md"), renderAgentsMd(next));
38428
+ writeFileSync2(join11(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync7(join11(skillPath, "SKILL.md"), "utf-8"), next));
38429
+ if (!existsSync7(join11(skillPath, "AGENTS.md")))
38430
+ writeFileSync2(join11(skillPath, "AGENTS.md"), renderAgentsMd(next));
38546
38431
  ensurePackageJson(skillPath, next);
38547
- if (!existsSync6(join9(skillPath, "tsconfig.json")))
38548
- writeFileSync2(join9(skillPath, "tsconfig.json"), renderTsconfig());
38432
+ if (!existsSync7(join11(skillPath, "tsconfig.json")))
38433
+ writeFileSync2(join11(skillPath, "tsconfig.json"), renderTsconfig());
38549
38434
  writeSkillJsonWithHash(skillPath, next);
38550
38435
  return readPortableSkillManifest(skillPath, next.name);
38551
38436
  }
38552
38437
  function ensurePackageJson(skillPath, manifest) {
38553
- const pkgPath = join9(skillPath, "package.json");
38438
+ const pkgPath = join11(skillPath, "package.json");
38554
38439
  const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
38555
38440
  const commandName = normalizePortableSkillName(first.name || manifest.name);
38556
38441
  const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
38557
- if (!existsSync6(pkgPath)) {
38442
+ if (!existsSync7(pkgPath)) {
38558
38443
  writeFileSync2(pkgPath, renderPackageJson(manifest));
38559
38444
  return;
38560
38445
  }
@@ -38597,8 +38482,8 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
38597
38482
  inputs: [],
38598
38483
  commands: []
38599
38484
  };
38600
- if (!existsSync6(join9(skillPath, "SKILL.md"))) {
38601
- writeFileSync2(join9(skillPath, "SKILL.md"), renderSkillMd(next));
38485
+ if (!existsSync7(join11(skillPath, "SKILL.md"))) {
38486
+ writeFileSync2(join11(skillPath, "SKILL.md"), renderSkillMd(next));
38602
38487
  }
38603
38488
  writeSkillJsonWithHash(skillPath, next);
38604
38489
  return readPortableSkillManifest(skillPath, next.name);
@@ -38890,18 +38775,18 @@ var LEGACY_CUSTOM_DIRNAME = "custom";
38890
38775
  function getPortableSkillsRoot(options = {}) {
38891
38776
  if (options.rootDir)
38892
38777
  return options.rootDir;
38893
- const appDir = options.homeDir ? join10(options.homeDir, ".hasna", "skills") : getDataDir();
38894
- const cache3 = join10(appDir, SKILLS_CACHE_DIRNAME);
38778
+ const appDir = options.homeDir ? join12(options.homeDir, ".hasna", "skills") : getDataDir();
38779
+ const cache3 = join12(appDir, SKILLS_CACHE_DIRNAME);
38895
38780
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache3))
38896
38781
  return cache3;
38897
- const installed = join10(appDir, INSTALLED_SKILLS_DIRNAME);
38782
+ const installed = join12(appDir, INSTALLED_SKILLS_DIRNAME);
38898
38783
  migrateLegacySkillLayout(appDir, installed);
38899
38784
  return installed;
38900
38785
  }
38901
38786
  function looksLikeSkillDirectory(path) {
38902
38787
  if (!safeIsDirectory(path))
38903
38788
  return false;
38904
- return existsSync7(join10(path, "SKILL.md")) || existsSync7(join10(path, "skill.json")) || existsSync7(join10(path, "package.json"));
38789
+ return existsSync8(join12(path, "SKILL.md")) || existsSync8(join12(path, "skill.json")) || existsSync8(join12(path, "package.json"));
38905
38790
  }
38906
38791
  function migrateLegacySkillLayout(appDir, installed) {
38907
38792
  if (!safeIsDirectory(appDir))
@@ -38911,7 +38796,7 @@ function migrateLegacySkillLayout(appDir, installed) {
38911
38796
  for (const entry of readdirSync6(appDir)) {
38912
38797
  if (entry.startsWith(".") || entry === INSTALLED_SKILLS_DIRNAME)
38913
38798
  continue;
38914
- const path = join10(appDir, entry);
38799
+ const path = join12(appDir, entry);
38915
38800
  if (entry === LEGACY_CUSTOM_DIRNAME) {
38916
38801
  if (!safeIsDirectory(path))
38917
38802
  continue;
@@ -38919,7 +38804,7 @@ function migrateLegacySkillLayout(appDir, installed) {
38919
38804
  for (const nested of readdirSync6(path)) {
38920
38805
  if (nested.startsWith("."))
38921
38806
  continue;
38922
- const nestedPath = join10(path, nested);
38807
+ const nestedPath = join12(path, nested);
38923
38808
  if (looksLikeSkillDirectory(nestedPath))
38924
38809
  candidates.push({ from: nestedPath, name: nested });
38925
38810
  }
@@ -38933,10 +38818,10 @@ function migrateLegacySkillLayout(appDir, installed) {
38933
38818
  return;
38934
38819
  }
38935
38820
  for (const { from, name } of candidates) {
38936
- const target = join10(installed, name);
38937
- if (existsSync7(target))
38821
+ const target = join12(installed, name);
38822
+ if (existsSync8(target))
38938
38823
  continue;
38939
- const staging = join10(installed, `.migrating-${name}-${process.pid}`);
38824
+ const staging = join12(installed, `.migrating-${name}-${process.pid}`);
38940
38825
  try {
38941
38826
  rmSync(staging, { recursive: true, force: true });
38942
38827
  cpSync2(from, staging, { recursive: true, errorOnExist: false });
@@ -38949,7 +38834,7 @@ function migrateLegacySkillLayout(appDir, installed) {
38949
38834
  }
38950
38835
  }
38951
38836
  function getPortableSkillPath(name, options = {}) {
38952
- return join10(getPortableSkillsRoot(options), normalizePortableSkillName(name));
38837
+ return join12(getPortableSkillsRoot(options), normalizePortableSkillName(name));
38953
38838
  }
38954
38839
  function findPortableSkill(name, options = {}) {
38955
38840
  let normalized;
@@ -38959,7 +38844,7 @@ function findPortableSkill(name, options = {}) {
38959
38844
  return null;
38960
38845
  }
38961
38846
  const path = getPortableSkillPath(normalized, options);
38962
- if (!existsSync7(path) || !statSync6(path).isDirectory())
38847
+ if (!existsSync8(path) || !statSync6(path).isDirectory())
38963
38848
  return null;
38964
38849
  try {
38965
38850
  return summarizePortableSkill(path, normalized);
@@ -38975,7 +38860,7 @@ function listPortableSkills(options = {}) {
38975
38860
  for (const entry of readdirSync6(root3).sort()) {
38976
38861
  if (entry.startsWith("."))
38977
38862
  continue;
38978
- const path = join10(root3, entry);
38863
+ const path = join12(root3, entry);
38979
38864
  if (!safeIsDirectory(path))
38980
38865
  continue;
38981
38866
  try {
@@ -39009,8 +38894,8 @@ function isOfficialSkillName(name) {
39009
38894
  function scaffoldPortableSkill(name, options = {}) {
39010
38895
  const skillName = normalizePortableSkillName(name);
39011
38896
  const root3 = getPortableSkillsRoot(options);
39012
- const skillPath = join10(root3, skillName);
39013
- if (existsSync7(skillPath)) {
38897
+ const skillPath = join12(root3, skillName);
38898
+ if (existsSync8(skillPath)) {
39014
38899
  if (!options.overwrite)
39015
38900
  throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
39016
38901
  rmSync(skillPath, { recursive: true, force: true });
@@ -39028,7 +38913,7 @@ function scaffoldPortableSkill(name, options = {}) {
39028
38913
  }
39029
38914
  function portPortableSkillDirectory(sourceDir, options = {}) {
39030
38915
  const absoluteSource = normalize2(sourceDir);
39031
- if (!existsSync7(absoluteSource) || !statSync6(absoluteSource).isDirectory()) {
38916
+ if (!existsSync8(absoluteSource) || !statSync6(absoluteSource).isDirectory()) {
39032
38917
  throw new Error(`Import directory not found: ${sourceDir}`);
39033
38918
  }
39034
38919
  const continueOnError = options.continueOnError ?? true;
@@ -39041,7 +38926,7 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
39041
38926
  const skipped = [];
39042
38927
  const entries = readdirSync6(absoluteSource, { withFileTypes: true }).map((entry) => entry.name).filter((entryName) => !entryName.startsWith(".")).sort();
39043
38928
  for (const entryName of entries) {
39044
- const childPath = join10(absoluteSource, entryName);
38929
+ const childPath = join12(absoluteSource, entryName);
39045
38930
  if (!safeIsDirectory(childPath))
39046
38931
  continue;
39047
38932
  if (!isSkillCandidate(childPath)) {
@@ -39070,11 +38955,11 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
39070
38955
  };
39071
38956
  }
39072
38957
  function isSkillCandidate(dir) {
39073
- return existsSync7(join10(dir, "SKILL.md")) || existsSync7(join10(dir, "skill.json")) || existsSync7(join10(dir, "package.json"));
38958
+ return existsSync8(join12(dir, "SKILL.md")) || existsSync8(join12(dir, "skill.json")) || existsSync8(join12(dir, "package.json"));
39074
38959
  }
39075
38960
  function portPortableSkill(sourcePath, options = {}) {
39076
38961
  const absoluteSource = normalize2(sourcePath);
39077
- if (!existsSync7(absoluteSource) || !statSync6(absoluteSource).isDirectory()) {
38962
+ if (!existsSync8(absoluteSource) || !statSync6(absoluteSource).isDirectory()) {
39078
38963
  throw new Error(`Skill source directory not found: ${sourcePath}`);
39079
38964
  }
39080
38965
  const inferred = readPortableSkillManifest(absoluteSource, basename2(absoluteSource));
@@ -39086,8 +38971,8 @@ function portPortableSkill(sourcePath, options = {}) {
39086
38971
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
39087
38972
  }
39088
38973
  const root3 = getPortableSkillsRoot(options);
39089
- const destination = join10(root3, skillName);
39090
- if (existsSync7(destination)) {
38974
+ const destination = join12(root3, skillName);
38975
+ if (existsSync8(destination)) {
39091
38976
  if (!options.overwrite)
39092
38977
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
39093
38978
  rmSync(destination, { recursive: true, force: true });
@@ -39129,10 +39014,10 @@ function buildCorpusManifest(input, name) {
39129
39014
  function writeCorpusSkill(input, options = {}) {
39130
39015
  const name = normalizePortableSkillName(input.name);
39131
39016
  const root3 = getPortableSkillsRoot(options);
39132
- const skillPath = join10(root3, name);
39133
- const created = !existsSync7(skillPath);
39017
+ const skillPath = join12(root3, name);
39018
+ const created = !existsSync8(skillPath);
39134
39019
  mkdirSync5(skillPath, { recursive: true });
39135
- writeFileSync3(join10(skillPath, "SKILL.md"), input.skillMd);
39020
+ writeFileSync3(join12(skillPath, "SKILL.md"), input.skillMd);
39136
39021
  const manifest = buildCorpusManifest(input, name);
39137
39022
  writeSkillJsonWithHash(skillPath, manifest);
39138
39023
  return { name, path: skillPath, manifest, created };
@@ -39140,19 +39025,19 @@ function writeCorpusSkill(input, options = {}) {
39140
39025
  function installCorpusSkillAtomically(input, options = {}) {
39141
39026
  const name = normalizePortableSkillName(input.name);
39142
39027
  const root3 = getPortableSkillsRoot(options);
39143
- const target = join10(root3, name);
39144
- const created = !existsSync7(target);
39028
+ const target = join12(root3, name);
39029
+ const created = !existsSync8(target);
39145
39030
  mkdirSync5(root3, { recursive: true });
39146
- const staging = mkdtempSync(join10(root3, `.pull-${name}-`));
39031
+ const staging = mkdtempSync(join12(root3, `.pull-${name}-`));
39147
39032
  let moved = false;
39148
39033
  let backup = null;
39149
39034
  try {
39150
- writeFileSync3(join10(staging, "SKILL.md"), input.skillMd);
39035
+ writeFileSync3(join12(staging, "SKILL.md"), input.skillMd);
39151
39036
  const manifest = buildCorpusManifest(input, name);
39152
39037
  writeSkillJsonWithHash(staging, manifest);
39153
- if (existsSync7(target)) {
39154
- backup = mkdtempSync(join10(root3, `.pull-backup-${name}-`));
39155
- renameSync(target, join10(backup, name));
39038
+ if (existsSync8(target)) {
39039
+ backup = mkdtempSync(join12(root3, `.pull-backup-${name}-`));
39040
+ renameSync(target, join12(backup, name));
39156
39041
  moved = true;
39157
39042
  }
39158
39043
  renameSync(staging, target);
@@ -39161,9 +39046,9 @@ function installCorpusSkillAtomically(input, options = {}) {
39161
39046
  return { name, path: target, manifest, created };
39162
39047
  } catch (error) {
39163
39048
  rmSync(staging, { recursive: true, force: true });
39164
- if (moved && backup && existsSync7(join10(backup, name))) {
39049
+ if (moved && backup && existsSync8(join12(backup, name))) {
39165
39050
  try {
39166
- renameSync(join10(backup, name), target);
39051
+ renameSync(join12(backup, name), target);
39167
39052
  } catch {}
39168
39053
  }
39169
39054
  throw error;
@@ -39175,10 +39060,10 @@ function validatePortableSkillDirectory(name, skillPath) {
39175
39060
  const issues = [...base.issues];
39176
39061
  const warnings = [...base.warnings];
39177
39062
  let manifest;
39178
- if (existsSync7(skillPath)) {
39179
- const skillJsonPath = join10(skillPath, "skill.json");
39180
- const skillMdPath = join10(skillPath, "SKILL.md");
39181
- if (!existsSync7(skillJsonPath) && !existsSync7(skillMdPath)) {
39063
+ if (existsSync8(skillPath)) {
39064
+ const skillJsonPath = join12(skillPath, "skill.json");
39065
+ const skillMdPath = join12(skillPath, "SKILL.md");
39066
+ if (!existsSync8(skillJsonPath) && !existsSync8(skillMdPath)) {
39182
39067
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
39183
39068
  }
39184
39069
  try {
@@ -39197,7 +39082,7 @@ function validatePortableSkillDirectory(name, skillPath) {
39197
39082
  add3(issues, "portable.version_missing", "Portable manifest missing version");
39198
39083
  }
39199
39084
  const contractIssues = validatePortableManifestContract(manifest, {
39200
- strict: existsSync7(join10(skillPath, "skill.json")),
39085
+ strict: existsSync8(join12(skillPath, "skill.json")),
39201
39086
  skillPath
39202
39087
  });
39203
39088
  for (const issue of contractIssues)
@@ -39233,8 +39118,8 @@ function validatePortableSkillDirectory(name, skillPath) {
39233
39118
  add3(issues, "portable.command_entry_unsafe", `Command '${command3.name}' entry '${command3.entry}' must stay inside the skill directory`);
39234
39119
  continue;
39235
39120
  }
39236
- const entryPath = join10(skillPath, command3.entry);
39237
- if (!existsSync7(entryPath))
39121
+ const entryPath = join12(skillPath, command3.entry);
39122
+ if (!existsSync8(entryPath))
39238
39123
  add3(issues, "portable.command_entry_missing", `Command '${command3.name}' entry '${command3.entry}' is missing`);
39239
39124
  else if (statSync6(entryPath).isDirectory())
39240
39125
  add3(issues, "portable.command_entry_directory", `Command '${command3.name}' entry '${command3.entry}' must be a file`);
@@ -39244,7 +39129,7 @@ function validatePortableSkillDirectory(name, skillPath) {
39244
39129
  } catch (error) {
39245
39130
  add3(issues, "portable.manifest_invalid", error.message);
39246
39131
  }
39247
- if (manifest?.kind !== "instruction" && !existsSync7(join10(skillPath, "AGENTS.md"))) {
39132
+ if (manifest?.kind !== "instruction" && !existsSync8(join12(skillPath, "AGENTS.md"))) {
39248
39133
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
39249
39134
  }
39250
39135
  }
@@ -39280,13 +39165,13 @@ async function runPortableSkill(name, args, options = {}) {
39280
39165
  if (!isSafeRelativePath2(command3.entry)) {
39281
39166
  return { exitCode: 1, error: `Portable skill '${name}' command entry is unsafe` };
39282
39167
  }
39283
- const entryPath = join10(skill.path, command3.entry);
39284
- if (!existsSync7(entryPath)) {
39168
+ const entryPath = join12(skill.path, command3.entry);
39169
+ if (!existsSync8(entryPath)) {
39285
39170
  return { exitCode: 1, error: `Entry point '${command3.entry}' not found in portable skill '${name}'` };
39286
39171
  }
39287
- const pkgPath = join10(skill.path, "package.json");
39288
- const nodeModules = join10(skill.path, "node_modules");
39289
- if (existsSync7(pkgPath) && !existsSync7(nodeModules) && hasPackageDependencies(pkgPath)) {
39172
+ const pkgPath = join12(skill.path, "package.json");
39173
+ const nodeModules = join12(skill.path, "node_modules");
39174
+ if (existsSync8(pkgPath) && !existsSync8(nodeModules) && hasPackageDependencies(pkgPath)) {
39290
39175
  const install = Bun.spawn(["bun", "install", "--no-save"], {
39291
39176
  cwd: skill.path,
39292
39177
  stdout: "pipe",
@@ -39508,7 +39393,7 @@ function parseSkillMdFrontmatter(content) {
39508
39393
  return Object.keys(result).length > 0 ? result : null;
39509
39394
  }
39510
39395
  function discoverSkillsInDir(dir, source = "custom") {
39511
- if (!existsSync8(dir))
39396
+ if (!existsSync9(dir))
39512
39397
  return [];
39513
39398
  const result = [];
39514
39399
  try {
@@ -39516,8 +39401,8 @@ function discoverSkillsInDir(dir, source = "custom") {
39516
39401
  for (const entry of entries) {
39517
39402
  if (!entry.isDirectory())
39518
39403
  continue;
39519
- const skillMdPath = join11(dir, entry.name, "SKILL.md");
39520
- if (!existsSync8(skillMdPath))
39404
+ const skillMdPath = join13(dir, entry.name, "SKILL.md");
39405
+ if (!existsSync9(skillMdPath))
39521
39406
  continue;
39522
39407
  let content;
39523
39408
  try {
@@ -39536,7 +39421,7 @@ function discoverSkillsInDir(dir, source = "custom") {
39536
39421
  category: fm.category || "Development Tools",
39537
39422
  tags: fm.tags || [],
39538
39423
  ...fm.kind ? { kind: fm.kind } : {},
39539
- ...isHostedMetadataSkillDir(join11(dir, entry.name)) ? { serverOwned: true } : {},
39424
+ ...isHostedMetadataSkillDir(join13(dir, entry.name)) ? { serverOwned: true } : {},
39540
39425
  source
39541
39426
  });
39542
39427
  }
@@ -39545,16 +39430,16 @@ function discoverSkillsInDir(dir, source = "custom") {
39545
39430
  }
39546
39431
  function findExtensionSkillPath(name) {
39547
39432
  const config = loadConfig4();
39548
- if (!config.extensionsDir || !existsSync8(config.extensionsDir))
39433
+ if (!config.extensionsDir || !existsSync9(config.extensionsDir))
39549
39434
  return null;
39550
39435
  try {
39551
39436
  const entries = readdirSync7(config.extensionsDir, { withFileTypes: true });
39552
39437
  for (const entry of entries) {
39553
39438
  if (!entry.isDirectory())
39554
39439
  continue;
39555
- const skillDir = join11(config.extensionsDir, entry.name);
39556
- const skillMdPath = join11(skillDir, "SKILL.md");
39557
- if (!existsSync8(skillMdPath))
39440
+ const skillDir = join13(config.extensionsDir, entry.name);
39441
+ const skillMdPath = join13(skillDir, "SKILL.md");
39442
+ if (!existsSync9(skillMdPath))
39558
39443
  continue;
39559
39444
  let content;
39560
39445
  try {
@@ -39586,12 +39471,12 @@ function loadRegistry(cwd) {
39586
39471
  if (registryCache && registryCacheKey === rootKey && now - registryCacheTime < REGISTRY_CACHE_TTL) {
39587
39472
  return registryCache;
39588
39473
  }
39589
- const dataDir = getDataDir();
39474
+ const dataDir2 = getDataDir();
39590
39475
  const config = loadConfig4();
39591
39476
  const official = SKILLS.map((s2) => ({ ...s2, source: "official" }));
39592
39477
  const extensions = config.extensionsDir ? discoverSkillsInDir(config.extensionsDir, "extension") : [];
39593
39478
  const portableCustom = listPortableSkillMetas();
39594
- const legacyCustom = discoverSkillsInDir(join11(dataDir, "custom"));
39479
+ const legacyCustom = discoverSkillsInDir(join13(dataDir2, "custom"));
39595
39480
  const globalCustom = mergeCustomSkills([...legacyCustom, ...portableCustom]);
39596
39481
  registryCache = mergeSkillRegistryLists(official, extensions, globalCustom);
39597
39482
  registryCacheTime = now;
@@ -39639,19 +39524,19 @@ function getAllTags() {
39639
39524
  }
39640
39525
 
39641
39526
  // src/lib/skillinfo.ts
39642
- import { existsSync as existsSync12, readFileSync as readFileSync12 } from "fs";
39643
- import { join as join15 } from "path";
39527
+ import { existsSync as existsSync13, readFileSync as readFileSync12 } from "fs";
39528
+ import { join as join17 } from "path";
39644
39529
 
39645
39530
  // src/lib/installer.ts
39646
- import { existsSync as existsSync11, readFileSync as readFileSync11, rmSync as rmSync3 } from "fs";
39647
- import { dirname as dirname9, join as join14 } from "path";
39648
- import { homedir as homedir4 } from "os";
39531
+ import { existsSync as existsSync12, readFileSync as readFileSync11, rmSync as rmSync3 } from "fs";
39532
+ import { dirname as dirname9, join as join16 } from "path";
39533
+ import { homedir as homedir5 } from "os";
39649
39534
  import { fileURLToPath as fileURLToPath2 } from "url";
39650
39535
 
39651
39536
  // src/lib/agent-sync.ts
39652
39537
  import {
39653
39538
  cpSync as cpSync3,
39654
- existsSync as existsSync9,
39539
+ existsSync as existsSync10,
39655
39540
  mkdirSync as mkdirSync6,
39656
39541
  mkdtempSync as mkdtempSync2,
39657
39542
  readFileSync as readFileSync9,
@@ -39661,8 +39546,8 @@ import {
39661
39546
  statSync as statSync7,
39662
39547
  writeFileSync as writeFileSync4
39663
39548
  } from "fs";
39664
- import { homedir as homedir3 } from "os";
39665
- import { basename as basename3, dirname as dirname8, join as join12 } from "path";
39549
+ import { homedir as homedir4 } from "os";
39550
+ import { basename as basename3, dirname as dirname8, join as join14 } from "path";
39666
39551
  // src/lib/home-migration.ts
39667
39552
  function resolveCorpusRoot(options = {}) {
39668
39553
  return getPortableSkillsRoot(options);
@@ -39684,12 +39569,12 @@ function resolveSyncAgents(arg) {
39684
39569
  }
39685
39570
  return [arg];
39686
39571
  }
39687
- function agentGlobalSkillsDir(agent, homeDir = homedir3()) {
39572
+ function agentGlobalSkillsDir(agent, homeDir = homedir4()) {
39688
39573
  switch (agent) {
39689
39574
  case "opencode":
39690
- return join12(homeDir, ".config", "opencode", "skills");
39575
+ return join14(homeDir, ".config", "opencode", "skills");
39691
39576
  default:
39692
- return join12(homeDir, `.${agent}`, "skills");
39577
+ return join14(homeDir, `.${agent}`, "skills");
39693
39578
  }
39694
39579
  }
39695
39580
  function adaptSkillMdForAgent(skillMd, agent) {
@@ -39748,8 +39633,8 @@ function resolveSyncCorpus(options = {}) {
39748
39633
  function packageSourceRoots(source) {
39749
39634
  const roots = [];
39750
39635
  for (const sub of ["skills"]) {
39751
- const candidate = join12(source, sub);
39752
- if (existsSync9(candidate) && isDirectory(candidate))
39636
+ const candidate = join14(source, sub);
39637
+ if (existsSync10(candidate) && isDirectory(candidate))
39753
39638
  roots.push(candidate);
39754
39639
  }
39755
39640
  if (roots.length > 0)
@@ -39764,10 +39649,10 @@ function containsSkillDirectories(path) {
39764
39649
  return false;
39765
39650
  }
39766
39651
  return entries.some((entry) => {
39767
- const candidate = join12(path, entry);
39652
+ const candidate = join14(path, entry);
39768
39653
  if (!isDirectory(candidate))
39769
39654
  return false;
39770
- return existsSync9(join12(candidate, "SKILL.md")) || existsSync9(join12(candidate, "skill.json")) || existsSync9(join12(candidate, "package.json"));
39655
+ return existsSync10(join14(candidate, "SKILL.md")) || existsSync10(join14(candidate, "skill.json")) || existsSync10(join14(candidate, "package.json"));
39771
39656
  });
39772
39657
  }
39773
39658
  function isDirectory(path) {
@@ -39780,7 +39665,7 @@ function isDirectory(path) {
39780
39665
  function syncSkillsToAgents(options = {}) {
39781
39666
  const requested = normalizeRequested(options.names);
39782
39667
  const agents = options.agents?.length ? options.agents : [...SYNC_AGENTS];
39783
- const homeDir = options.homeDir ?? homedir3();
39668
+ const homeDir = options.homeDir ?? homedir4();
39784
39669
  const { roots, source } = resolveSyncCorpus(options);
39785
39670
  const corpus = listPortableSkillsAcrossRoots(roots);
39786
39671
  const byName = new Map(corpus.map((skill) => [skill.name, skill]));
@@ -39806,7 +39691,7 @@ function syncSkillsToAgents(options = {}) {
39806
39691
  actions.push({
39807
39692
  skill: name,
39808
39693
  agent,
39809
- path: join12(agentGlobalSkillsDir(agent, homeDir), name, "SKILL.md"),
39694
+ path: join14(agentGlobalSkillsDir(agent, homeDir), name, "SKILL.md"),
39810
39695
  action: "skip",
39811
39696
  reason: "not found in this machine's corpus"
39812
39697
  });
@@ -39835,8 +39720,8 @@ function syncSkillsToAgents(options = {}) {
39835
39720
  return { actions };
39836
39721
  }
39837
39722
  function writeManagedAgentSkill(params) {
39838
- const homeDir = params.homeDir ?? homedir3();
39839
- const dir = join12(agentGlobalSkillsDir(params.agent, homeDir), params.skill);
39723
+ const homeDir = params.homeDir ?? homedir4();
39724
+ const dir = join14(agentGlobalSkillsDir(params.agent, homeDir), params.skill);
39840
39725
  const result = writeManagedSkillDir(dir, params.skillMd, {
39841
39726
  skill: params.skill,
39842
39727
  source: params.source,
@@ -39853,11 +39738,11 @@ function writeManagedAgentSkill(params) {
39853
39738
  };
39854
39739
  }
39855
39740
  function writeManagedSkillDir(dir, skillMd, options) {
39856
- const skillMdPath = join12(dir, "SKILL.md");
39857
- const markerPath = join12(dir, SYNC_MARKER_FILE);
39858
- const dirExists = existsSync9(dir);
39859
- const managed = existsSync9(markerPath);
39860
- const hasSkillMd = existsSync9(skillMdPath);
39741
+ const skillMdPath = join14(dir, "SKILL.md");
39742
+ const markerPath = join14(dir, SYNC_MARKER_FILE);
39743
+ const dirExists = existsSync10(dir);
39744
+ const managed = existsSync10(markerPath);
39745
+ const hasSkillMd = existsSync10(skillMdPath);
39861
39746
  if (dirExists && !managed && !hasSkillMd) {
39862
39747
  return {
39863
39748
  action: "skip",
@@ -39892,11 +39777,11 @@ function writeManagedSkillDir(dir, skillMd, options) {
39892
39777
  return { action, path: skillMdPath };
39893
39778
  const parentDir = dirname8(dir);
39894
39779
  mkdirSync6(parentDir, { recursive: true });
39895
- const transactionDir = mkdtempSync2(join12(parentDir, `.hasna-skills-write-${basename3(dir)}-`));
39896
- const candidateDir = join12(transactionDir, "candidate");
39897
- const backupDir = join12(transactionDir, "backup");
39898
- const candidateSkillMdPath = join12(candidateDir, "SKILL.md");
39899
- const candidateMarkerPath = join12(candidateDir, SYNC_MARKER_FILE);
39780
+ const transactionDir = mkdtempSync2(join14(parentDir, `.hasna-skills-write-${basename3(dir)}-`));
39781
+ const candidateDir = join14(transactionDir, "candidate");
39782
+ const backupDir = join14(transactionDir, "backup");
39783
+ const candidateSkillMdPath = join14(candidateDir, "SKILL.md");
39784
+ const candidateMarkerPath = join14(candidateDir, SYNC_MARKER_FILE);
39900
39785
  const marker = {
39901
39786
  managedBy: SYNC_MARKER_MANAGED_BY,
39902
39787
  skill: options.skill,
@@ -39923,9 +39808,9 @@ function writeManagedSkillDir(dir, skillMd, options) {
39923
39808
  }
39924
39809
  renameDirectory(candidateDir, dir);
39925
39810
  } catch (error) {
39926
- if (originalMoved && existsSync9(backupDir)) {
39811
+ if (originalMoved && existsSync10(backupDir)) {
39927
39812
  try {
39928
- if (existsSync9(dir))
39813
+ if (existsSync10(dir))
39929
39814
  rmSync2(dir, { recursive: true, force: true });
39930
39815
  renameDirectory(backupDir, dir);
39931
39816
  originalMoved = false;
@@ -39944,17 +39829,17 @@ function writeManagedSkillDir(dir, skillMd, options) {
39944
39829
  }
39945
39830
  return { action, path: skillMdPath };
39946
39831
  }
39947
- function removeManagedAgentSkill(skill, agent, homeDir = homedir3()) {
39948
- const dir = join12(agentGlobalSkillsDir(agent, homeDir), skill);
39949
- if (!existsSync9(join12(dir, SYNC_MARKER_FILE)))
39832
+ function removeManagedAgentSkill(skill, agent, homeDir = homedir4()) {
39833
+ const dir = join14(agentGlobalSkillsDir(agent, homeDir), skill);
39834
+ if (!existsSync10(join14(dir, SYNC_MARKER_FILE)))
39950
39835
  return false;
39951
39836
  rmSync2(dir, { recursive: true, force: true });
39952
39837
  return true;
39953
39838
  }
39954
39839
  function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = false) {
39955
39840
  if (kind === undefined || kind === "instruction" || preferBundledDocs) {
39956
- const skillMdPath = join12(skillPath, "SKILL.md");
39957
- if (existsSync9(skillMdPath))
39841
+ const skillMdPath = join14(skillPath, "SKILL.md");
39842
+ if (existsSync10(skillMdPath))
39958
39843
  return readFileSync9(skillMdPath, "utf-8");
39959
39844
  }
39960
39845
  return pointerSkillMd(name, description);
@@ -39985,8 +39870,8 @@ function normalizeSkillName(name) {
39985
39870
  }
39986
39871
 
39987
39872
  // src/lib/project-state.ts
39988
- import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
39989
- import { join as join13 } from "path";
39873
+ import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
39874
+ import { join as join15 } from "path";
39990
39875
  var VALID_PIN_SOURCES = [
39991
39876
  "official",
39992
39877
  "custom",
@@ -40001,14 +39886,14 @@ var SKILLS_PROJECT_DIR = ".skills";
40001
39886
  var PROJECT_CONFIG_FILE = "project.json";
40002
39887
  var DEFAULT_EXPORT_DIR = ".skills/exports";
40003
39888
  function getProjectStateDir(targetDir = process.cwd()) {
40004
- return join13(targetDir, SKILLS_PROJECT_DIR);
39889
+ return join15(targetDir, SKILLS_PROJECT_DIR);
40005
39890
  }
40006
39891
  function getProjectConfigPath(targetDir = process.cwd()) {
40007
- return join13(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
39892
+ return join15(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
40008
39893
  }
40009
39894
  function loadProjectConfig(targetDir = process.cwd()) {
40010
39895
  const path = getProjectConfigPath(targetDir);
40011
- if (!existsSync10(path))
39896
+ if (!existsSync11(path))
40012
39897
  return null;
40013
39898
  try {
40014
39899
  return normalizeProjectConfig(JSON.parse(readFileSync10(path, "utf-8")));
@@ -40129,12 +40014,12 @@ var __dirname2 = dirname9(fileURLToPath2(import.meta.url));
40129
40014
  function findSkillsDir() {
40130
40015
  let dir = __dirname2;
40131
40016
  for (let i3 = 0;i3 < 5; i3++) {
40132
- const candidate = join14(dir, "skills");
40133
- if (existsSync11(candidate) && !dir.includes(".skills"))
40017
+ const candidate = join16(dir, "skills");
40018
+ if (existsSync12(candidate) && !dir.includes(".skills"))
40134
40019
  return candidate;
40135
40020
  dir = dirname9(dir);
40136
40021
  }
40137
- return join14(__dirname2, "..", "skills");
40022
+ return join16(__dirname2, "..", "skills");
40138
40023
  }
40139
40024
  var SKILLS_DIR = findSkillsDir();
40140
40025
  function getSkillPath(name) {
@@ -40142,25 +40027,25 @@ function getSkillPath(name) {
40142
40027
  const portable = findPortableSkill(skillName);
40143
40028
  if (portable)
40144
40029
  return portable.path;
40145
- const legacyCustomPath = join14(getDataDir(), "custom", skillName);
40146
- if (existsSync11(legacyCustomPath))
40030
+ const legacyCustomPath = join16(getDataDir(), "custom", skillName);
40031
+ if (existsSync12(legacyCustomPath))
40147
40032
  return legacyCustomPath;
40148
40033
  const extensionPath = findExtensionSkillPath(skillName);
40149
40034
  if (extensionPath)
40150
40035
  return extensionPath;
40151
- return join14(SKILLS_DIR, skillName);
40036
+ return join16(SKILLS_DIR, skillName);
40152
40037
  }
40153
40038
  function getCanonicalSkillName(name) {
40154
40039
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
40155
40040
  }
40156
40041
  function skillExists(name) {
40157
- return existsSync11(getSkillPath(name));
40042
+ return existsSync12(getSkillPath(name));
40158
40043
  }
40159
40044
  function installSkill(name, options = {}) {
40160
40045
  const { targetDir = process.cwd(), overwrite = false } = options;
40161
40046
  const canonicalName = getCanonicalSkillName(name);
40162
40047
  const skillName = normalizeSkillName(canonicalName);
40163
- if (!existsSync11(getSkillPath(name))) {
40048
+ if (!existsSync12(getSkillPath(name))) {
40164
40049
  const knownOfficial = Boolean(getSkill(name));
40165
40050
  return {
40166
40051
  skill: canonicalName,
@@ -40187,7 +40072,7 @@ function installSkill(name, options = {}) {
40187
40072
  }
40188
40073
  function installSkillSource(name, _options = {}) {
40189
40074
  const canonicalName = getCanonicalSkillName(name);
40190
- if (!existsSync11(getSkillPath(name))) {
40075
+ if (!existsSync12(getSkillPath(name))) {
40191
40076
  return { skill: canonicalName, success: false, error: `Skill '${name}' not found`, mode: "source" };
40192
40077
  }
40193
40078
  return {
@@ -40208,11 +40093,11 @@ function installSkillManifest(manifest, _options = {}) {
40208
40093
  }
40209
40094
  function createLocalSkillManifest(name, generateSkillMd) {
40210
40095
  const sourcePath = getSkillPath(name);
40211
- if (!existsSync11(sourcePath))
40096
+ if (!existsSync12(sourcePath))
40212
40097
  return null;
40213
40098
  let skillMd = "";
40214
- const skillMdPath = join14(sourcePath, "SKILL.md");
40215
- if (existsSync11(skillMdPath)) {
40099
+ const skillMdPath = join16(sourcePath, "SKILL.md");
40100
+ if (existsSync12(skillMdPath)) {
40216
40101
  skillMd = readFileSync11(skillMdPath, "utf-8");
40217
40102
  } else if (generateSkillMd) {
40218
40103
  skillMd = generateSkillMd(name) ?? "";
@@ -40285,20 +40170,20 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
40285
40170
  const base = projectDir || process.cwd();
40286
40171
  switch (agent) {
40287
40172
  case "pi":
40288
- return scope === "project" ? join14(base, ".pi", "skills") : join14(homedir4(), ".pi", "agent", "skills");
40173
+ return scope === "project" ? join16(base, ".pi", "skills") : join16(homedir5(), ".pi", "agent", "skills");
40289
40174
  case "opencode":
40290
- return scope === "project" ? join14(base, ".opencode", "skills") : join14(homedir4(), ".config", "opencode", "skills");
40175
+ return scope === "project" ? join16(base, ".opencode", "skills") : join16(homedir5(), ".config", "opencode", "skills");
40291
40176
  default:
40292
- return scope === "project" ? join14(base, `.${agent}`, "skills") : join14(homedir4(), `.${agent}`, "skills");
40177
+ return scope === "project" ? join16(base, `.${agent}`, "skills") : join16(homedir5(), `.${agent}`, "skills");
40293
40178
  }
40294
40179
  }
40295
40180
  function getAgentSkillPath(name, agent, scope = "global", projectDir) {
40296
40181
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
40297
- return join14(getAgentSkillsDir(agent, scope, projectDir), skillName);
40182
+ return join16(getAgentSkillsDir(agent, scope, projectDir), skillName);
40298
40183
  }
40299
40184
  function installSkillForAgent(name, options, generateSkillMd) {
40300
40185
  const canonicalName = getCanonicalSkillName(name);
40301
- if (!existsSync11(getSkillPath(name))) {
40186
+ if (!existsSync12(getSkillPath(name))) {
40302
40187
  return { skill: canonicalName, success: false, error: `Skill '${name}' not found` };
40303
40188
  }
40304
40189
  const scope = options.scope ?? "global";
@@ -40322,15 +40207,15 @@ function removeSkillForAgent(name, options) {
40322
40207
  const canonicalName = getCanonicalSkillName(name);
40323
40208
  const scope = options.scope ?? "global";
40324
40209
  const dir = getAgentSkillPath(canonicalName, options.agent, scope, options.projectDir);
40325
- if (!existsSync11(join14(dir, SYNC_MARKER_FILE)))
40210
+ if (!existsSync12(join16(dir, SYNC_MARKER_FILE)))
40326
40211
  return false;
40327
40212
  rmSync3(dir, { recursive: true, force: true });
40328
40213
  return true;
40329
40214
  }
40330
40215
  function resolveAgentSkillMd(name, generateSkillMd) {
40331
40216
  const sourcePath = getSkillPath(name);
40332
- const skillMdPath = join14(sourcePath, "SKILL.md");
40333
- if (existsSync11(skillMdPath))
40217
+ const skillMdPath = join16(sourcePath, "SKILL.md");
40218
+ if (existsSync12(skillMdPath))
40334
40219
  return readFileSync11(skillMdPath, "utf-8");
40335
40220
  if (generateSkillMd)
40336
40221
  return generateSkillMd(name);
@@ -40349,7 +40234,7 @@ function warnMissingDependencies(name, targetDir) {
40349
40234
  }
40350
40235
  function generateMinimalSkillMd(name) {
40351
40236
  const sourcePath = getSkillPath(name);
40352
- if (!existsSync11(sourcePath))
40237
+ if (!existsSync12(sourcePath))
40353
40238
  return null;
40354
40239
  const canonicalName = getCanonicalSkillName(name);
40355
40240
  const meta = getSkill(canonicalName);
@@ -40364,7 +40249,7 @@ function generateMinimalSkillMd(name) {
40364
40249
  "---",
40365
40250
  ""
40366
40251
  ].filter(Boolean);
40367
- const fallbackDoc = readFileIfExists(join14(sourcePath, "README.md")) || readFileIfExists(join14(sourcePath, "CLAUDE.md"));
40252
+ const fallbackDoc = readFileIfExists(join16(sourcePath, "README.md")) || readFileIfExists(join16(sourcePath, "CLAUDE.md"));
40368
40253
  if (fallbackDoc)
40369
40254
  return `${frontmatter.join(`
40370
40255
  `)}${fallbackDoc.trim()}
@@ -40383,8 +40268,8 @@ skills run ${canonicalName}
40383
40268
  `;
40384
40269
  }
40385
40270
  function readBundledSkillVersion(name) {
40386
- const pkgPath = join14(getSkillPath(name), "package.json");
40387
- if (!existsSync11(pkgPath))
40271
+ const pkgPath = join16(getSkillPath(name), "package.json");
40272
+ if (!existsSync12(pkgPath))
40388
40273
  return "unknown";
40389
40274
  try {
40390
40275
  const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
@@ -40394,7 +40279,7 @@ function readBundledSkillVersion(name) {
40394
40279
  }
40395
40280
  }
40396
40281
  function readFileIfExists(path) {
40397
- return existsSync11(path) ? readFileSync11(path, "utf-8") : null;
40282
+ return existsSync12(path) ? readFileSync11(path, "utf-8") : null;
40398
40283
  }
40399
40284
  function loadProjectConfigCompat(targetDir) {
40400
40285
  return loadProjectConfig(targetDir);
@@ -40404,8 +40289,8 @@ function loadProjectConfigCompat(targetDir) {
40404
40289
  function isInstructionSkillDir(skillPath, meta) {
40405
40290
  if (meta?.kind === "instruction")
40406
40291
  return true;
40407
- const skillMdPath = join15(skillPath, "SKILL.md");
40408
- if (!existsSync12(skillMdPath))
40292
+ const skillMdPath = join17(skillPath, "SKILL.md");
40293
+ if (!existsSync13(skillMdPath))
40409
40294
  return false;
40410
40295
  try {
40411
40296
  return parseSkillFrontmatter(readFileSync12(skillMdPath, "utf-8"))?.kind === "instruction";
@@ -40431,12 +40316,12 @@ var HOSTED_PROVIDER_ENV_PREFIXES = [
40431
40316
  ];
40432
40317
  function getSkillDocs(name) {
40433
40318
  const skillPath = getSkillPath(name);
40434
- if (!existsSync12(skillPath))
40319
+ if (!existsSync13(skillPath))
40435
40320
  return null;
40436
40321
  return {
40437
- skillMd: readIfExists(join15(skillPath, "SKILL.md")),
40438
- readme: readIfExists(join15(skillPath, "README.md")),
40439
- claudeMd: readIfExists(join15(skillPath, "CLAUDE.md"))
40322
+ skillMd: readIfExists(join17(skillPath, "SKILL.md")),
40323
+ readme: readIfExists(join17(skillPath, "README.md")),
40324
+ claudeMd: readIfExists(join17(skillPath, "CLAUDE.md"))
40440
40325
  };
40441
40326
  }
40442
40327
  function getSkillBestDoc(name) {
@@ -40447,11 +40332,11 @@ function getSkillBestDoc(name) {
40447
40332
  }
40448
40333
  function getSkillRequirements(name) {
40449
40334
  const skillPath = getSkillPath(name);
40450
- if (!existsSync12(skillPath))
40335
+ if (!existsSync13(skillPath))
40451
40336
  return null;
40452
40337
  const texts = [];
40453
40338
  for (const file of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
40454
- const content = readIfExists(join15(skillPath, file));
40339
+ const content = readIfExists(join17(skillPath, file));
40455
40340
  if (content)
40456
40341
  texts.push(content);
40457
40342
  }
@@ -40490,8 +40375,8 @@ function getSkillRequirements(name) {
40490
40375
  const skillName = normalizeSkillName(name);
40491
40376
  let cliCommand = `skills run ${skillName}`;
40492
40377
  let dependencies = {};
40493
- const pkgPath = join15(skillPath, "package.json");
40494
- if (existsSync12(pkgPath)) {
40378
+ const pkgPath = join17(skillPath, "package.json");
40379
+ if (existsSync13(pkgPath)) {
40495
40380
  try {
40496
40381
  const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
40497
40382
  dependencies = pkg.dependencies || {};
@@ -40511,7 +40396,7 @@ async function runSkill(name, args, options = {}) {
40511
40396
  const meta = getSkill(name);
40512
40397
  const canonicalName = meta?.name ?? name;
40513
40398
  const skillPath = getSkillPath(canonicalName);
40514
- if (!existsSync12(skillPath)) {
40399
+ if (!existsSync13(skillPath)) {
40515
40400
  return { exitCode: 1, error: `Skill '${name}' not found` };
40516
40401
  }
40517
40402
  if (isInstructionSkillDir(skillPath, meta)) {
@@ -40520,8 +40405,8 @@ async function runSkill(name, args, options = {}) {
40520
40405
  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'.`
40521
40406
  };
40522
40407
  }
40523
- const pkgPath = join15(skillPath, "package.json");
40524
- if (!existsSync12(pkgPath)) {
40408
+ const pkgPath = join17(skillPath, "package.json");
40409
+ if (!existsSync13(pkgPath)) {
40525
40410
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
40526
40411
  }
40527
40412
  let entryPoint;
@@ -40540,12 +40425,12 @@ async function runSkill(name, args, options = {}) {
40540
40425
  } catch {
40541
40426
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
40542
40427
  }
40543
- const entryPath = join15(skillPath, entryPoint);
40544
- if (!existsSync12(entryPath)) {
40428
+ const entryPath = join17(skillPath, entryPoint);
40429
+ if (!existsSync13(entryPath)) {
40545
40430
  return { exitCode: 1, error: `Entry point '${entryPoint}' not found in skill '${name}'` };
40546
40431
  }
40547
- const nodeModules = join15(skillPath, "node_modules");
40548
- if (!existsSync12(nodeModules)) {
40432
+ const nodeModules = join17(skillPath, "node_modules");
40433
+ if (!existsSync13(nodeModules)) {
40549
40434
  const install = Bun.spawn(["bun", "install", "--no-save"], {
40550
40435
  cwd: skillPath,
40551
40436
  stdout: "pipe",
@@ -40617,7 +40502,7 @@ function generateSkillMd(name) {
40617
40502
  if (!meta)
40618
40503
  return null;
40619
40504
  const skillPath = getSkillPath(name);
40620
- if (!existsSync12(skillPath))
40505
+ if (!existsSync13(skillPath))
40621
40506
  return null;
40622
40507
  const frontmatter = [
40623
40508
  "---",
@@ -40626,11 +40511,11 @@ function generateSkillMd(name) {
40626
40511
  "---"
40627
40512
  ].join(`
40628
40513
  `);
40629
- const readme = readIfExists(join15(skillPath, "README.md"));
40630
- const claudeMd = readIfExists(join15(skillPath, "CLAUDE.md"));
40514
+ const readme = readIfExists(join17(skillPath, "README.md"));
40515
+ const claudeMd = readIfExists(join17(skillPath, "CLAUDE.md"));
40631
40516
  let cliCommand = null;
40632
- const pkgPath = join15(skillPath, "package.json");
40633
- if (existsSync12(pkgPath)) {
40517
+ const pkgPath = join17(skillPath, "package.json");
40518
+ if (existsSync13(pkgPath)) {
40634
40519
  try {
40635
40520
  const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
40636
40521
  if (pkg.bin) {
@@ -40707,7 +40592,7 @@ function extractEnvVars(text) {
40707
40592
  }
40708
40593
  function readIfExists(path) {
40709
40594
  try {
40710
- if (existsSync12(path)) {
40595
+ if (existsSync13(path)) {
40711
40596
  return readFileSync12(path, "utf-8");
40712
40597
  }
40713
40598
  } catch {}
@@ -40745,11 +40630,11 @@ function getServerSkillMd(slug) {
40745
40630
  const docs = getSkillDocs(name);
40746
40631
  if (docs?.skillMd)
40747
40632
  return docs.skillMd;
40748
- const skillsDir = resolve(process.cwd(), "skills");
40749
- const path = resolve(skillsDir, name, "SKILL.md");
40633
+ const skillsDir = resolve2(process.cwd(), "skills");
40634
+ const path = resolve2(skillsDir, name, "SKILL.md");
40750
40635
  if (!isInsideDir(skillsDir, path))
40751
40636
  return null;
40752
- return existsSync13(path) ? readFileSync13(path, "utf8") : null;
40637
+ return existsSync14(path) ? readFileSync13(path, "utf8") : null;
40753
40638
  }
40754
40639
 
40755
40640
  // src/server/skills-api.ts
@@ -41159,6 +41044,9 @@ async function createSkillsFetchHandler(options = {}) {
41159
41044
  if (request.method === "GET" && url.pathname === "/ready") {
41160
41045
  return json({ ok: true, service: "skills" });
41161
41046
  }
41047
+ if (request.method === "GET" && url.pathname === "/version") {
41048
+ return json({ ok: true, service: "skills", version: package_default.version });
41049
+ }
41162
41050
  if (url.pathname.startsWith("/api/")) {
41163
41051
  const principal = await authenticateRequest(store, request);
41164
41052
  if (!principal)
@@ -46377,7 +46265,7 @@ var commonParams3 = {
46377
46265
  UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" }
46378
46266
  };
46379
46267
  // ../../node_modules/.bun/@aws-sdk+client-ecs@3.1112.0/node_modules/@aws-sdk/client-ecs/package.json
46380
- var package_default2 = {
46268
+ var package_default3 = {
46381
46269
  name: "@aws-sdk/client-ecs",
46382
46270
  version: "3.1112.0",
46383
46271
  description: "AWS SDK for JavaScript Ecs Client for Node.js, Browser and React Native",
@@ -49410,7 +49298,7 @@ var getRuntimeConfig5 = (config) => {
49410
49298
  authSchemePreference: config?.authSchemePreference ?? import_config38.loadConfig(import_httpAuthSchemes6.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig),
49411
49299
  bodyLengthChecker: config?.bodyLengthChecker ?? import_serde6.calculateBodyLength,
49412
49300
  credentialDefaultProvider: config?.credentialDefaultProvider ?? defaultProvider,
49413
- defaultUserAgentProvider: config?.defaultUserAgentProvider ?? import_client29.createDefaultUserAgentProvider({ serviceId: clientSharedValues.serviceId, clientVersion: package_default2.version }),
49301
+ defaultUserAgentProvider: config?.defaultUserAgentProvider ?? import_client29.createDefaultUserAgentProvider({ serviceId: clientSharedValues.serviceId, clientVersion: package_default3.version }),
49414
49302
  maxAttempts: config?.maxAttempts ?? import_config38.loadConfig(import_retry5.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config),
49415
49303
  region: config?.region ?? import_config38.loadConfig(import_config38.NODE_REGION_CONFIG_OPTIONS, { ...import_config38.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }),
49416
49304
  requestHandler: import_node_http_handler3.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider),