@hasna/skills 0.10.1 → 0.10.3

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
@@ -7173,9 +7173,9 @@ var require_transport = __commonJS((exports) => {
7173
7173
  }
7174
7174
  return true;
7175
7175
  };
7176
- function isValidHostname(hostname) {
7176
+ function isValidHostname(hostname2) {
7177
7177
  const hostPattern = /^[a-z0-9][a-z0-9.-]*[a-z0-9]$/;
7178
- return hostPattern.test(hostname);
7178
+ return hostPattern.test(hostname2);
7179
7179
  }
7180
7180
  var normalizeProvider = (input) => {
7181
7181
  if (typeof input === "function")
@@ -7208,13 +7208,13 @@ var require_transport = __commonJS((exports) => {
7208
7208
  if (typeof url === "string") {
7209
7209
  return parseUrl(new URL(url));
7210
7210
  }
7211
- const { hostname, pathname, port, protocol, search } = url;
7211
+ const { hostname: hostname2, pathname, port, protocol, search } = url;
7212
7212
  let query;
7213
7213
  if (search) {
7214
7214
  query = parseQueryString(search);
7215
7215
  }
7216
7216
  return {
7217
- hostname,
7217
+ hostname: hostname2,
7218
7218
  port: port ? parseInt(port) : undefined,
7219
7219
  protocol,
7220
7220
  path: pathname,
@@ -9399,11 +9399,11 @@ var require_config = __commonJS((exports) => {
9399
9399
  }
9400
9400
  const useDualstackEndpoint = await input.useDualstackEndpoint();
9401
9401
  const useFipsEndpoint = await input.useFipsEndpoint();
9402
- const { hostname } = await input.regionInfoProvider(region, { useDualstackEndpoint, useFipsEndpoint }) ?? {};
9403
- if (!hostname) {
9402
+ const { hostname: hostname2 } = await input.regionInfoProvider(region, { useDualstackEndpoint, useFipsEndpoint }) ?? {};
9403
+ if (!hostname2) {
9404
9404
  throw new Error("Cannot resolve hostname from client config");
9405
9405
  }
9406
- return input.urlParser(`${tls ? "https:" : "http:"}//${hostname}`);
9406
+ return input.urlParser(`${tls ? "https:" : "http:"}//${hostname2}`);
9407
9407
  };
9408
9408
  var resolveEndpointsConfig = (input) => {
9409
9409
  const useDualstackEndpoint = normalizeProvider(input.useDualstackEndpoint ?? false);
@@ -9566,12 +9566,12 @@ var require_config = __commonJS((exports) => {
9566
9566
  var getHostnameFromVariants = (variants = [], { useFipsEndpoint, useDualstackEndpoint }) => variants.find(({ tags }) => useFipsEndpoint === tags.includes("fips") && useDualstackEndpoint === tags.includes("dualstack"))?.hostname;
9567
9567
  var getResolvedHostname = (resolvedRegion, { regionHostname, partitionHostname }) => regionHostname ? regionHostname : partitionHostname ? partitionHostname.replace("{region}", resolvedRegion) : undefined;
9568
9568
  var getResolvedPartition = (region, { partitionHash }) => Object.keys(partitionHash || {}).find((key) => partitionHash[key].regions.includes(region)) ?? "aws";
9569
- var getResolvedSigningRegion = (hostname, { signingRegion, regionRegex, useFipsEndpoint }) => {
9569
+ var getResolvedSigningRegion = (hostname2, { signingRegion, regionRegex, useFipsEndpoint }) => {
9570
9570
  if (signingRegion) {
9571
9571
  return signingRegion;
9572
9572
  } else if (useFipsEndpoint) {
9573
9573
  const regionRegexJs = regionRegex.replace("\\\\", "\\").replace(/^\^/g, "\\.").replace(/\$$/g, "\\.");
9574
- const regionRegexmatchArray = hostname.match(regionRegexJs);
9574
+ const regionRegexmatchArray = hostname2.match(regionRegexJs);
9575
9575
  if (regionRegexmatchArray) {
9576
9576
  return regionRegexmatchArray[0].slice(1, -1);
9577
9577
  }
@@ -9583,11 +9583,11 @@ var require_config = __commonJS((exports) => {
9583
9583
  const hostnameOptions = { useFipsEndpoint, useDualstackEndpoint };
9584
9584
  const regionHostname = getHostnameFromVariants(regionHash[resolvedRegion]?.variants, hostnameOptions);
9585
9585
  const partitionHostname = getHostnameFromVariants(partitionHash[partition]?.variants, hostnameOptions);
9586
- const hostname = getResolvedHostname(resolvedRegion, { regionHostname, partitionHostname });
9587
- if (hostname === undefined) {
9586
+ const hostname2 = getResolvedHostname(resolvedRegion, { regionHostname, partitionHostname });
9587
+ if (hostname2 === undefined) {
9588
9588
  throw new Error(`Endpoint resolution failed for: ${{ resolvedRegion, useFipsEndpoint, useDualstackEndpoint }}`);
9589
9589
  }
9590
- const signingRegion = getResolvedSigningRegion(hostname, {
9590
+ const signingRegion = getResolvedSigningRegion(hostname2, {
9591
9591
  signingRegion: regionHash[resolvedRegion]?.signingRegion,
9592
9592
  regionRegex: partitionHash[partition].regionRegex,
9593
9593
  useFipsEndpoint
@@ -9595,7 +9595,7 @@ var require_config = __commonJS((exports) => {
9595
9595
  return {
9596
9596
  partition,
9597
9597
  signingService,
9598
- hostname,
9598
+ hostname: hostname2,
9599
9599
  ...signingRegion && { signingRegion },
9600
9600
  ...regionHash[resolvedRegion]?.signingService && {
9601
9601
  signingService: regionHash[resolvedRegion].signingService
@@ -9820,8 +9820,8 @@ var require_endpoints = __commonJS((exports) => {
9820
9820
  return endpoint.url.href;
9821
9821
  }
9822
9822
  if ("hostname" in endpoint) {
9823
- const { protocol, hostname, port, path } = endpoint;
9824
- return `${protocol}//${hostname}${port ? ":" + port : ""}${path}`;
9823
+ const { protocol, hostname: hostname2, port, path } = endpoint;
9824
+ return `${protocol}//${hostname2}${port ? ":" + port : ""}${path}`;
9825
9825
  }
9826
9826
  }
9827
9827
  return endpoint;
@@ -10128,8 +10128,8 @@ var require_endpoints = __commonJS((exports) => {
10128
10128
  return value;
10129
10129
  }
10130
10130
  if (typeof value === "object" && "hostname" in value) {
10131
- const { hostname: hostname2, port, protocol: protocol2 = "", path = "", query = {} } = value;
10132
- const url = new URL(`${protocol2}//${hostname2}${port ? `:${port}` : ""}${path}`);
10131
+ const { hostname: hostname3, port, protocol: protocol2 = "", path = "", query = {} } = value;
10132
+ const url = new URL(`${protocol2}//${hostname3}${port ? `:${port}` : ""}${path}`);
10133
10133
  url.search = Object.entries(query).map(([k, v]) => `${k}=${v}`).join("&");
10134
10134
  return url;
10135
10135
  }
@@ -10143,7 +10143,7 @@ var require_endpoints = __commonJS((exports) => {
10143
10143
  return null;
10144
10144
  }
10145
10145
  const urlString = whatwgURL.href;
10146
- const { host, hostname, pathname, protocol, search } = whatwgURL;
10146
+ const { host, hostname: hostname2, pathname, protocol, search } = whatwgURL;
10147
10147
  if (search) {
10148
10148
  return null;
10149
10149
  }
@@ -10151,7 +10151,7 @@ var require_endpoints = __commonJS((exports) => {
10151
10151
  if (!Object.values(EndpointURLScheme).includes(scheme)) {
10152
10152
  return null;
10153
10153
  }
10154
- const isIp = isIpAddress(hostname);
10154
+ const isIp = isIpAddress(hostname2);
10155
10155
  const inputContainsDefaultPort = urlString.includes(`${host}:${DEFAULT_PORTS[scheme]}`) || typeof value === "string" && value.includes(`${host}:${DEFAULT_PORTS[scheme]}`);
10156
10156
  const authority2 = `${host}${inputContainsDefaultPort ? `:${DEFAULT_PORTS[scheme]}` : ``}`;
10157
10157
  return {
@@ -14232,14 +14232,14 @@ var require_protocols = __commonJS((exports) => {
14232
14232
  this.context = context;
14233
14233
  }
14234
14234
  async build() {
14235
- const { hostname, protocol = "https", port, path: basePath } = await this.context.endpoint();
14235
+ const { hostname: hostname2, protocol = "https", port, path: basePath } = await this.context.endpoint();
14236
14236
  this.path = basePath;
14237
14237
  for (const resolvePath of this.resolvePathStack) {
14238
14238
  resolvePath(this.path);
14239
14239
  }
14240
14240
  return new HttpRequest({
14241
14241
  protocol,
14242
- hostname: this.hostname || hostname,
14242
+ hostname: this.hostname || hostname2,
14243
14243
  port,
14244
14244
  method: this.method,
14245
14245
  path: this.path,
@@ -14248,8 +14248,8 @@ var require_protocols = __commonJS((exports) => {
14248
14248
  headers: this.headers
14249
14249
  });
14250
14250
  }
14251
- hn(hostname) {
14252
- this.hostname = hostname;
14251
+ hn(hostname2) {
14252
+ this.hostname = hostname2;
14253
14253
  return this;
14254
14254
  }
14255
14255
  bp(uriLabel) {
@@ -18564,12 +18564,12 @@ var require_util = __commonJS((exports) => {
18564
18564
  };
18565
18565
  function formatUrl(request2) {
18566
18566
  const { port, query } = request2;
18567
- let { protocol, path, hostname } = request2;
18567
+ let { protocol, path, hostname: hostname2 } = request2;
18568
18568
  if (protocol && protocol.slice(-1) !== ":") {
18569
18569
  protocol += ":";
18570
18570
  }
18571
18571
  if (port) {
18572
- hostname += `:${port}`;
18572
+ hostname2 += `:${port}`;
18573
18573
  }
18574
18574
  if (path && path.charAt(0) !== "/") {
18575
18575
  path = `/${path}`;
@@ -18588,7 +18588,7 @@ var require_util = __commonJS((exports) => {
18588
18588
  if (request2.fragment) {
18589
18589
  fragment = `#${request2.fragment}`;
18590
18590
  }
18591
- return `${protocol}//${auth}${hostname}${path}${queryString}${fragment}`;
18591
+ return `${protocol}//${auth}${hostname2}${path}${queryString}${fragment}`;
18592
18592
  }
18593
18593
  exports.build = build;
18594
18594
  exports.formatUrl = formatUrl;
@@ -19477,10 +19477,10 @@ var require_cbor = __commonJS((exports) => {
19477
19477
  };
19478
19478
  var buildHttpRpcRequest = async (context, headers, path, resolvedHostname, body) => {
19479
19479
  const endpoint = await context.endpoint();
19480
- const { hostname, protocol = "https", port, path: basePath } = endpoint;
19480
+ const { hostname: hostname2, protocol = "https", port, path: basePath } = endpoint;
19481
19481
  const contents = {
19482
19482
  protocol,
19483
- hostname,
19483
+ hostname: hostname2,
19484
19484
  port,
19485
19485
  method: "POST",
19486
19486
  path: basePath.endsWith("/") ? basePath.slice(0, -1) + path : basePath + path,
@@ -25338,15 +25338,15 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25338
25338
  if (request2.fragment) {
25339
25339
  path += `#${request2.fragment}`;
25340
25340
  }
25341
- let hostname = request2.hostname ?? "";
25342
- if (hostname[0] === "[" && hostname.endsWith("]")) {
25343
- hostname = request2.hostname.slice(1, -1);
25341
+ let hostname2 = request2.hostname ?? "";
25342
+ if (hostname2[0] === "[" && hostname2.endsWith("]")) {
25343
+ hostname2 = request2.hostname.slice(1, -1);
25344
25344
  } else {
25345
- hostname = request2.hostname;
25345
+ hostname2 = request2.hostname;
25346
25346
  }
25347
25347
  const nodeHttpsOptions = {
25348
25348
  headers: request2.headers,
25349
- host: hostname,
25349
+ host: hostname2,
25350
25350
  method: request2.method,
25351
25351
  path,
25352
25352
  port: request2.port,
@@ -25738,14 +25738,14 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
25738
25738
  reject(abortError);
25739
25739
  return;
25740
25740
  }
25741
- const { hostname, method, port, protocol, query } = request2;
25741
+ const { hostname: hostname2, method, port, protocol, query } = request2;
25742
25742
  let auth = "";
25743
25743
  if (request2.username != null || request2.password != null) {
25744
25744
  const username = request2.username ?? "";
25745
25745
  const password = request2.password ?? "";
25746
25746
  auth = `${username}:${password}@`;
25747
25747
  }
25748
- const authority2 = `${protocol}//${auth}${hostname}${port ? `:${port}` : ""}`;
25748
+ const authority2 = `${protocol}//${auth}${hostname2}${port ? `:${port}` : ""}`;
25749
25749
  const requestContext = { destination: new URL(authority2) };
25750
25750
  const connectConfig = {
25751
25751
  requestTimeout: this.config?.sessionTimeout,
@@ -30946,7 +30946,7 @@ var fromWebToken = (init) => async (awsIdentityProperties) => {
30946
30946
  };
30947
30947
 
30948
30948
  // node_modules/@aws-sdk/credential-provider-web-identity/dist-es/fromTokenFile.js
30949
- import { readFileSync as readFileSync21 } from "fs";
30949
+ import { readFileSync as readFileSync22 } from "fs";
30950
30950
  var import_client19, import_config32, ENV_TOKEN_FILE = "AWS_WEB_IDENTITY_TOKEN_FILE", ENV_ROLE_ARN = "AWS_ROLE_ARN", ENV_ROLE_SESSION_NAME = "AWS_ROLE_SESSION_NAME", fromTokenFile = (init = {}) => async (awsIdentityProperties) => {
30951
30951
  init.logger?.debug("@aws-sdk/credential-provider-web-identity - fromTokenFile");
30952
30952
  const webIdentityTokenFile = init?.webIdentityTokenFile ?? process.env[ENV_TOKEN_FILE];
@@ -30959,7 +30959,7 @@ var import_client19, import_config32, ENV_TOKEN_FILE = "AWS_WEB_IDENTITY_TOKEN_F
30959
30959
  }
30960
30960
  const credentials = await fromWebToken({
30961
30961
  ...init,
30962
- webIdentityToken: import_config32.externalDataInterceptor?.getTokenRecord?.()[webIdentityTokenFile] ?? readFileSync21(webIdentityTokenFile, { encoding: "ascii" }),
30962
+ webIdentityToken: import_config32.externalDataInterceptor?.getTokenRecord?.()[webIdentityTokenFile] ?? readFileSync22(webIdentityTokenFile, { encoding: "ascii" }),
30963
30963
  roleArn,
30964
30964
  roleSessionName
30965
30965
  })(awsIdentityProperties);
@@ -31530,42 +31530,42 @@ function isPrivateAddress(address) {
31530
31530
  return true;
31531
31531
  }
31532
31532
  async function resolveWebhookTarget(url, policy = {}) {
31533
- const hostname = normalizeHostname(url.hostname);
31533
+ const hostname2 = normalizeHostname(url.hostname);
31534
31534
  const allowlist = (policy.allowPrivateHosts ?? []).map((entry) => normalizeHostname(entry.toLowerCase()));
31535
- if (allowlist.includes(hostname)) {
31536
- const version22 = isIP3(hostname);
31535
+ if (allowlist.includes(hostname2)) {
31536
+ const version22 = isIP3(hostname2);
31537
31537
  if (version22 === 4 || version22 === 6) {
31538
- return { hostname, addresses: [hostname] };
31538
+ return { hostname: hostname2, addresses: [hostname2] };
31539
31539
  }
31540
31540
  const lookup2 = policy.lookup ?? defaultTargetLookup;
31541
31541
  let resolved2;
31542
31542
  try {
31543
- resolved2 = await lookup2(hostname);
31543
+ resolved2 = await lookup2(hostname2);
31544
31544
  } catch {
31545
- throw new Error(`Webhook target ${hostname} could not be resolved`);
31545
+ throw new Error(`Webhook target ${hostname2} could not be resolved`);
31546
31546
  }
31547
31547
  if (!Array.isArray(resolved2) || resolved2.length === 0) {
31548
- throw new Error(`Webhook target ${hostname} resolved to no addresses`);
31548
+ throw new Error(`Webhook target ${hostname2} resolved to no addresses`);
31549
31549
  }
31550
31550
  const addresses = resolved2.map((entry) => normalizeHostname(entry.address));
31551
- return { hostname, addresses };
31551
+ return { hostname: hostname2, addresses };
31552
31552
  }
31553
- const version2 = isIP3(hostname);
31553
+ const version2 = isIP3(hostname2);
31554
31554
  if (version2 === 4 || version2 === 6) {
31555
- if (isPrivateAddress(hostname)) {
31556
- throw new Error(`Webhook target ${hostname} is a private or special-use address`);
31555
+ if (isPrivateAddress(hostname2)) {
31556
+ throw new Error(`Webhook target ${hostname2} is a private or special-use address`);
31557
31557
  }
31558
- return { hostname, addresses: [hostname] };
31558
+ return { hostname: hostname2, addresses: [hostname2] };
31559
31559
  }
31560
31560
  const lookup = policy.lookup ?? defaultTargetLookup;
31561
31561
  let resolved;
31562
31562
  try {
31563
- resolved = await lookup(hostname);
31563
+ resolved = await lookup(hostname2);
31564
31564
  } catch {
31565
- throw new Error(`Webhook target ${hostname} could not be resolved`);
31565
+ throw new Error(`Webhook target ${hostname2} could not be resolved`);
31566
31566
  }
31567
31567
  if (!Array.isArray(resolved) || resolved.length === 0) {
31568
- throw new Error(`Webhook target ${hostname} resolved to no addresses`);
31568
+ throw new Error(`Webhook target ${hostname2} resolved to no addresses`);
31569
31569
  }
31570
31570
  const allowed = [];
31571
31571
  for (const entry of resolved) {
@@ -31575,14 +31575,14 @@ async function resolveWebhookTarget(url, policy = {}) {
31575
31575
  allowed.push(address);
31576
31576
  continue;
31577
31577
  }
31578
- throw new Error(`Webhook target ${hostname} resolves to private or special-use address ${address}`);
31578
+ throw new Error(`Webhook target ${hostname2} resolves to private or special-use address ${address}`);
31579
31579
  }
31580
31580
  allowed.push(address);
31581
31581
  }
31582
31582
  if (allowed.length === 0) {
31583
- throw new Error(`Webhook target ${hostname} resolved to no public addresses`);
31583
+ throw new Error(`Webhook target ${hostname2} resolved to no public addresses`);
31584
31584
  }
31585
- return { hostname, addresses: allowed };
31585
+ return { hostname: hostname2, addresses: allowed };
31586
31586
  }
31587
31587
  function normalizeMaxRedirects(value) {
31588
31588
  if (value === undefined)
@@ -31591,8 +31591,8 @@ function normalizeMaxRedirects(value) {
31591
31591
  throw new Error("webhookTargetPolicy.maxRedirects must be a non-negative integer");
31592
31592
  return value;
31593
31593
  }
31594
- function normalizeHostname(hostname) {
31595
- const lower = hostname.toLowerCase();
31594
+ function normalizeHostname(hostname2) {
31595
+ const lower = hostname2.toLowerCase();
31596
31596
  if (lower.startsWith("[") && lower.endsWith("]"))
31597
31597
  return lower.slice(1, -1);
31598
31598
  return lower;
@@ -31785,7 +31785,7 @@ async function pinnedNativeRequest(target, addresses, method, headers, body4, si
31785
31785
  method,
31786
31786
  headers,
31787
31787
  ...tls?.ca ? { ca: tls.ca } : {},
31788
- lookup: (hostname, _options, callback) => {
31788
+ lookup: (hostname2, _options, callback) => {
31789
31789
  const entries = addresses.map((address) => ({
31790
31790
  address,
31791
31791
  family: address.includes(":") ? 6 : 4
@@ -32291,8 +32291,8 @@ function normalizeRetryPolicy(policy) {
32291
32291
  multiplier: Math.max(1, policy?.multiplier ?? 2)
32292
32292
  };
32293
32293
  }
32294
- var PATHS_RESOLVER_KIND_ENV, PATHS_RESOLVER_APP_SLUG_RE3, HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR", HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME", EVENTS_STORE_SENTINEL_FILE = "events.json", 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) => {
32295
- return dnsLookup(hostname, { all: true, verbatim: false });
32294
+ var PATHS_RESOLVER_KIND_ENV, PATHS_RESOLVER_APP_SLUG_RE3, HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR", HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME", EVENTS_STORE_SENTINEL_FILE = "events.json", 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 (hostname2) => {
32295
+ return dnsLookup(hostname2, { all: true, verbatim: false });
32296
32296
  }, EventValidationError, defaultEventTypeCatalog, APP_EVENT_V1_MAX_DATA_BYTES;
32297
32297
  var init_dist = __esm(() => {
32298
32298
  PATHS_RESOLVER_KIND_ENV = {
@@ -32373,7 +32373,7 @@ var init_event_sink = __esm(() => {
32373
32373
  // package.json
32374
32374
  var package_default = {
32375
32375
  name: "@hasna/skills",
32376
- version: "0.10.1",
32376
+ version: "0.10.3",
32377
32377
  description: "Skills library for AI coding agents",
32378
32378
  type: "module",
32379
32379
  bin: {
@@ -33974,7 +33974,9 @@ import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
33974
33974
 
33975
33975
  // src/lib/selection-cache.ts
33976
33976
  import { createHash as createHash3, randomUUID } from "crypto";
33977
- import { closeSync as closeSync5, constants as constants2, fstatSync as fstatSync5, fsyncSync, lstatSync as lstatSync3, mkdirSync as mkdirSync2, openSync as openSync5, readSync as readSync2, renameSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
33977
+ import { spawnSync as spawnSync2 } from "child_process";
33978
+ import { closeSync as closeSync5, constants as constants2, fstatSync as fstatSync5, fsyncSync, lstatSync as lstatSync3, mkdirSync as mkdirSync2, openSync as openSync5, readFileSync as readFileSync6, readlinkSync, readSync as readSync2, renameSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
33979
+ import { hostname } from "os";
33978
33980
  import { dirname as dirname3, join as join7, parse, resolve as resolve2 } from "path";
33979
33981
  import { isDeepStrictEqual } from "util";
33980
33982
 
@@ -35189,6 +35191,166 @@ function readSkillSessionSnapshot(sessionId, options = {}) {
35189
35191
  function skillSessionSnapshotBinding(snapshot) {
35190
35192
  return { sessionId: snapshot.sessionId, generation: snapshot.generation, receiptSha256: snapshot.receiptSha256 };
35191
35193
  }
35194
+ var SESSION_LOCK_MAX_BYTES = 4096;
35195
+ var SESSION_LOCK_MIN_AGE_MS = 30000;
35196
+ function localBootId() {
35197
+ try {
35198
+ if (process.platform === "linux") {
35199
+ const value = readFileSync6("/proc/sys/kernel/random/boot_id", "utf8").trim();
35200
+ return /^[a-f0-9-]{36}$/i.test(value) ? value : null;
35201
+ }
35202
+ if (process.platform === "darwin") {
35203
+ const result = spawnSync2("/usr/sbin/sysctl", ["-n", "kern.boottime"], { encoding: "utf8", timeout: 3000, env: { LC_ALL: "C" } });
35204
+ if (result.status !== 0 || result.error)
35205
+ return null;
35206
+ const seconds = /\bsec\s*=\s*(\d+)\b/.exec(result.stdout)?.[1];
35207
+ return seconds ? `darwin:${seconds}` : null;
35208
+ }
35209
+ } catch {}
35210
+ return null;
35211
+ }
35212
+ function processStart(pid) {
35213
+ if (!Number.isSafeInteger(pid) || pid <= 0)
35214
+ return { state: "unknown" };
35215
+ if (process.platform === "linux") {
35216
+ try {
35217
+ const stat = readFileSync6(`/proc/${pid}/stat`, "utf8");
35218
+ const close = stat.lastIndexOf(")");
35219
+ const start = close < 0 ? undefined : stat.slice(close + 2).trim().split(/\s+/)[19];
35220
+ return start && /^\d+$/.test(start) ? { state: "alive", start: `linux:${start}` } : { state: "unknown" };
35221
+ } catch (error) {
35222
+ return { state: error.code === "ENOENT" ? "absent" : "unknown" };
35223
+ }
35224
+ }
35225
+ if (process.platform === "darwin") {
35226
+ const result = spawnSync2("/bin/ps", ["-p", String(pid), "-o", "lstart="], { encoding: "utf8", timeout: 3000, env: { LC_ALL: "C" } });
35227
+ if (result.error || result.signal)
35228
+ return { state: "unknown" };
35229
+ const start = result.stdout.trim();
35230
+ if (result.status === 1 && !start && !result.stderr.trim())
35231
+ return { state: "absent" };
35232
+ return result.status === 0 && start ? { state: "alive", start: `darwin:${start}` } : { state: "unknown" };
35233
+ }
35234
+ return { state: "unknown" };
35235
+ }
35236
+ function localLockIdentity() {
35237
+ const bootId = localBootId(), owner = processStart(process.pid);
35238
+ if (!bootId || owner.state !== "alive")
35239
+ return null;
35240
+ let pidNamespace;
35241
+ if (process.platform === "linux") {
35242
+ try {
35243
+ pidNamespace = readlinkSync("/proc/self/ns/pid");
35244
+ } catch {
35245
+ return null;
35246
+ }
35247
+ if (!/^pid:\[\d+\]$/.test(pidNamespace))
35248
+ return null;
35249
+ }
35250
+ return { host: hostname(), bootId, pidNamespace, processStart: owner.start };
35251
+ }
35252
+ function readSessionLock(sessionId, options) {
35253
+ const path = `${sessionReceiptPath(sessionId, options)}.write-lock`;
35254
+ const before = lstatSync3(path, { throwIfNoEntry: false });
35255
+ if (!before)
35256
+ return null;
35257
+ if (!before.isFile() || before.nlink !== 1 || process.getuid && before.uid !== process.getuid()) {
35258
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is not a private regular file; recovery requires review.");
35259
+ }
35260
+ const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
35261
+ const after = lstatSync3(path, { throwIfNoEntry: false });
35262
+ if (!bytes || !after?.isFile() || before.dev !== after.dev || before.ino !== after.ino || before.mtimeMs !== after.mtimeMs) {
35263
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock changed during inspection; recovery requires review.");
35264
+ }
35265
+ let marker;
35266
+ try {
35267
+ marker = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
35268
+ } catch {
35269
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is unreadable; recovery requires review.");
35270
+ }
35271
+ if (!marker || ![1, 2].includes(marker.schemaVersion) || marker.sessionId !== sessionId || !/^[a-f0-9-]{36}$/i.test(marker.operationId) || !Number.isSafeInteger(marker.pid) || marker.pid <= 0 || marker.schemaVersion === 2 && (!marker.host || !marker.bootId || !marker.processStart || process.platform === "linux" && !marker.pidNamespace)) {
35272
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock has invalid ownership metadata; recovery requires review.");
35273
+ }
35274
+ return { path, bytes, marker, sha256: sha256Hex(bytes), dev: after.dev, ino: after.ino, mtimeMs: after.mtimeMs };
35275
+ }
35276
+ function writerIsGone(lock, explicitLocalHost) {
35277
+ if (Date.now() - lock.mtimeMs < SESSION_LOCK_MIN_AGE_MS)
35278
+ return false;
35279
+ const owner = processStart(lock.marker.pid);
35280
+ if (owner.state === "unknown")
35281
+ return false;
35282
+ if (lock.marker.schemaVersion === 1)
35283
+ return explicitLocalHost && owner.state === "absent";
35284
+ const local = localLockIdentity();
35285
+ if (!local || lock.marker.host !== local.host || lock.marker.bootId !== local.bootId || lock.marker.pidNamespace !== local.pidNamespace)
35286
+ return false;
35287
+ return owner.state === "absent" || owner.state === "alive" && owner.start !== lock.marker.processStart;
35288
+ }
35289
+ function archiveSessionLock(lock, receipt, explicitLocalHost) {
35290
+ const guardPath = `${lock.path}.recovery-guard`;
35291
+ let guardFd;
35292
+ try {
35293
+ guardFd = openSync5(guardPath, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, 384);
35294
+ } catch (error) {
35295
+ if (error.code === "EEXIST")
35296
+ return null;
35297
+ throw error;
35298
+ }
35299
+ const guardStat = fstatSync5(guardFd);
35300
+ try {
35301
+ writeFileSync2(guardFd, `${JSON.stringify({ schemaVersion: 1, pid: process.pid, operationId: randomUUID() })}
35302
+ `);
35303
+ fsyncSync(guardFd);
35304
+ const cacheOptions = { cacheDir: dirname3(dirname3(lock.path)) };
35305
+ const current = readSessionLock(lock.marker.sessionId, cacheOptions);
35306
+ if (!current || current.dev !== lock.dev || current.ino !== lock.ino || current.sha256 !== lock.sha256 || current.mtimeMs !== lock.mtimeMs || !writerIsGone(current, explicitLocalHost))
35307
+ return null;
35308
+ const currentReceipt = readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions);
35309
+ if (currentReceipt?.sha256 !== receipt?.sha256 || currentReceipt?.generation !== receipt?.generation)
35310
+ return null;
35311
+ const directory = join7(dirname3(dirname3(lock.path)), "session-lock-recoveries", randomUUID());
35312
+ const archivePath = join7(directory, "original.write-lock");
35313
+ const recordPath = join7(directory, "recovery.json");
35314
+ assertRegularPath(archivePath, true);
35315
+ archiveBytes(recordPath, Buffer.from(`${JSON.stringify({
35316
+ schemaVersion: 1,
35317
+ sessionId: lock.marker.sessionId,
35318
+ originalPath: lock.path,
35319
+ lockSha256: lock.sha256,
35320
+ lockMtime: new Date(lock.mtimeMs).toISOString(),
35321
+ lockPid: lock.marker.pid,
35322
+ receiptSha256: receipt?.sha256 ?? null,
35323
+ receiptGeneration: receipt?.generation ?? null,
35324
+ status: "prepared"
35325
+ })}
35326
+ `));
35327
+ syncDirectory(directory);
35328
+ syncDirectory(dirname3(directory));
35329
+ const finalLock = readSessionLock(lock.marker.sessionId, cacheOptions);
35330
+ if (!finalLock || finalLock.dev !== lock.dev || finalLock.ino !== lock.ino || finalLock.sha256 !== lock.sha256 || readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions)?.sha256 !== receipt?.sha256)
35331
+ return null;
35332
+ let moved = false;
35333
+ try {
35334
+ renameSync(lock.path, archivePath);
35335
+ moved = true;
35336
+ syncDirectory(directory);
35337
+ syncDirectory(dirname3(lock.path));
35338
+ if (sha256Hex(readRegularFile(archivePath, SESSION_LOCK_MAX_BYTES)) !== lock.sha256) {
35339
+ throw new Error("Archived lock bytes changed");
35340
+ }
35341
+ } catch (error) {
35342
+ if (moved)
35343
+ throw new SkillSelectionError("SESSION_LOCK_RECOVERY_INCOMPLETE", "The lock moved, but durable recovery could not be confirmed; inspect the preserved recovery directory and session receipt.");
35344
+ throw error;
35345
+ }
35346
+ return archivePath;
35347
+ } finally {
35348
+ closeSync5(guardFd);
35349
+ const current = lstatSync3(guardPath, { throwIfNoEntry: false });
35350
+ if (current?.isFile() && current.dev === guardStat.dev && current.ino === guardStat.ino)
35351
+ unlinkSync(guardPath);
35352
+ }
35353
+ }
35192
35354
  function withSessionWriteLocks(sessionIds, options, action) {
35193
35355
  const operationId = randomUUID();
35194
35356
  const locks = [...new Set(sessionIds)].map((sessionId) => ({ sessionId, path: `${sessionReceiptPath(sessionId, options)}.write-lock` })).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
@@ -35208,13 +35370,30 @@ function withSessionWriteLocks(sessionIds, options, action) {
35208
35370
  try {
35209
35371
  fd = openSync5(lock.path, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, 384);
35210
35372
  } catch (error) {
35211
- if (error.code === "EEXIST")
35212
- throw new SkillSelectionError("SESSION_WRITE_LOCKED", "Another Skills process owns a required session write lock; retry after it completes. A surviving lock requires explicit recovery review.");
35213
- throw error;
35373
+ if (error.code !== "EEXIST")
35374
+ throw error;
35375
+ try {
35376
+ const stale = readSessionLock(lock.sessionId, options);
35377
+ const receipt = stale && readSkillSessionSnapshotIfExists(lock.sessionId, options);
35378
+ if (stale?.marker.schemaVersion === 2 && writerIsGone(stale, false)) {
35379
+ archiveSessionLock(stale, receipt, false);
35380
+ }
35381
+ } catch (recoveryError) {
35382
+ if (recoveryError instanceof SkillSelectionError && recoveryError.code === "SESSION_LOCK_RECOVERY_INCOMPLETE")
35383
+ throw recoveryError;
35384
+ }
35385
+ try {
35386
+ fd = openSync5(lock.path, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, 384);
35387
+ } catch (retryError) {
35388
+ if (retryError.code === "EEXIST")
35389
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "Another Skills process owns a required session write lock; retry after it completes. A surviving legacy lock requires explicit recovery review.");
35390
+ throw retryError;
35391
+ }
35214
35392
  }
35215
35393
  const stat = fstatSync5(fd);
35216
35394
  owned.push({ path: lock.path, fd, dev: stat.dev, ino: stat.ino });
35217
- writeFileSync2(fd, `${JSON.stringify({ schemaVersion: 1, operationId, sessionId: lock.sessionId, pid: process.pid })}
35395
+ const identity = localLockIdentity();
35396
+ writeFileSync2(fd, `${JSON.stringify({ schemaVersion: identity ? 2 : 1, operationId, sessionId: lock.sessionId, pid: process.pid, ...identity })}
35218
35397
  `);
35219
35398
  }
35220
35399
  return action(assertOwned);
@@ -35341,8 +35520,8 @@ import { hostname as stationHostname } from "os";
35341
35520
 
35342
35521
  // node_modules/@hasna/secrets/dist/sdk.js
35343
35522
  import { isIP as isIP2 } from "net";
35344
- import { spawnSync as spawnSync2 } from "child_process";
35345
- import { closeSync as closeSync6, fstatSync as fstatSync6, openSync as openSync6, readFileSync as readFileSync6 } from "fs";
35523
+ import { spawnSync as spawnSync3 } from "child_process";
35524
+ import { closeSync as closeSync6, fstatSync as fstatSync6, openSync as openSync6, readFileSync as readFileSync7 } from "fs";
35346
35525
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
35347
35526
  import { createRequire as createRequire2 } from "module";
35348
35527
  import { hostname as osHostname2 } from "os";
@@ -35469,7 +35648,7 @@ function readAppConfigFile2(path) {
35469
35648
  unsafe("the file is not owned by the current user");
35470
35649
  if (before.size > MAX_CREDENTIAL_FILE_BYTES2)
35471
35650
  unsafe("the file exceeds the size limit");
35472
- const bytes = readFileSync6(fd);
35651
+ const bytes = readFileSync7(fd);
35473
35652
  const after = fstatSync6(fd);
35474
35653
  if (!configFileReadsCoherent2(before, after)) {
35475
35654
  unsafe("the file changed while being read");
@@ -35617,7 +35796,7 @@ function isAmbientEnvironment2(env) {
35617
35796
  return env === process.env || env[AMBIENT_ENVIRONMENT2] === true;
35618
35797
  }
35619
35798
  function defaultKeychainRunner2(argv) {
35620
- const result = spawnSync2(KEYCHAIN_SECURITY_BIN2, [...argv], {
35799
+ const result = spawnSync3(KEYCHAIN_SECURITY_BIN2, [...argv], {
35621
35800
  encoding: "utf8",
35622
35801
  stdio: ["ignore", "pipe", "pipe"],
35623
35802
  timeout: KEYCHAIN_SPAWN_TIMEOUT_MS2
@@ -37263,7 +37442,7 @@ import { dirname as dirname19, join as join31, resolve as resolve17 } from "path
37263
37442
  import { tmpdir, hostname as stationHostname2 } from "os";
37264
37443
 
37265
37444
  // src/lib/dependency-preparation.ts
37266
- import { constants as constants4, closeSync as closeSync8, fstatSync as fstatSync8, lstatSync as lstatSync4, mkdirSync as mkdirSync3, openSync as openSync8, readFileSync as readFileSync7, readdirSync as readdirSync2, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
37445
+ import { constants as constants4, closeSync as closeSync8, fstatSync as fstatSync8, lstatSync as lstatSync4, mkdirSync as mkdirSync3, openSync as openSync8, readFileSync as readFileSync8, readdirSync as readdirSync2, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
37267
37446
  import { join as join9 } from "path";
37268
37447
 
37269
37448
  // src/lib/preparation-process.ts
@@ -37337,7 +37516,7 @@ function claimPreparation(skillPath) {
37337
37516
  return;
37338
37517
  if (!lstatSync4(state).isFile() || lstatSync4(state).isSymbolicLink() || lstatSync4(state).size > 1024)
37339
37518
  return;
37340
- const previous = JSON.parse(readFileSync7(state, "utf8"));
37519
+ const previous = JSON.parse(readFileSync8(state, "utf8"));
37341
37520
  if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
37342
37521
  return;
37343
37522
  }
@@ -37470,11 +37649,11 @@ async function prepareSkillDependencies(skillPath, env, timeoutMs = DEFAULT_PREP
37470
37649
  }
37471
37650
 
37472
37651
  // src/lib/skillinfo.ts
37473
- import { existsSync as existsSync14, readFileSync as readFileSync20 } from "fs";
37652
+ import { existsSync as existsSync14, readFileSync as readFileSync21 } from "fs";
37474
37653
  import { join as join30 } from "path";
37475
37654
 
37476
37655
  // src/lib/installer.ts
37477
- import { existsSync as existsSync13, readFileSync as readFileSync19, rmSync as rmSync4 } from "fs";
37656
+ import { existsSync as existsSync13, readFileSync as readFileSync20, rmSync as rmSync4 } from "fs";
37478
37657
  import { join as join29 } from "path";
37479
37658
  import { homedir as homedir6 } from "os";
37480
37659
 
@@ -37485,7 +37664,7 @@ import {
37485
37664
  lstatSync as lstatSync21,
37486
37665
  mkdirSync as mkdirSync8,
37487
37666
  mkdtempSync as mkdtempSync2,
37488
- readFileSync as readFileSync16,
37667
+ readFileSync as readFileSync17,
37489
37668
  readdirSync as readdirSync10,
37490
37669
  renameSync as renameSync5,
37491
37670
  rmSync as rmSync3,
@@ -37516,7 +37695,7 @@ var NATIVE_SKILL_ROOTS = [
37516
37695
 
37517
37696
  // src/lib/agent-integration.ts
37518
37697
  import { createHash as createHash16, randomUUID as randomUUID3 } from "crypto";
37519
- import { existsSync as existsSync6, lstatSync as lstatSync18, statSync as statSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync13, readdirSync as readdirSync7, opendirSync as opendirSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync4, renameSync as renameSync3, rmdirSync as rmdirSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync4, chmodSync, openSync as openSync16, closeSync as closeSync16, fsyncSync as fsyncSync4, fstatSync as fstatSync16, readSync as readSync11, constants as constants12, linkSync as linkSync2 } from "fs";
37698
+ import { existsSync as existsSync6, lstatSync as lstatSync18, statSync as statSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync14, readdirSync as readdirSync7, opendirSync as opendirSync5, readlinkSync as readlinkSync3, realpathSync as realpathSync4, renameSync as renameSync3, rmdirSync as rmdirSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync4, chmodSync, openSync as openSync16, closeSync as closeSync16, fsyncSync as fsyncSync4, fstatSync as fstatSync16, readSync as readSync11, constants as constants12, linkSync as linkSync2 } from "fs";
37520
37699
  import { dirname as dirname14, join as join21, resolve as resolve14, relative as relative3, isAbsolute as isAbsolute15, sep as sep4 } from "path";
37521
37700
  import { homedir as homedir3 } from "os";
37522
37701
 
@@ -37705,7 +37884,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
37705
37884
 
37706
37885
  // src/lib/agent-bridge.ts
37707
37886
  import { createHash as createHash5 } from "crypto";
37708
- import { lstatSync as lstatSync6, readFileSync as readFileSync8, readdirSync as readdirSync3 } from "fs";
37887
+ import { lstatSync as lstatSync6, readFileSync as readFileSync9, readdirSync as readdirSync3 } from "fs";
37709
37888
  import { join as join11 } from "path";
37710
37889
  var CLI_BRIDGE_NAME = "skills-cli";
37711
37890
  var CLI_BRIDGE_VERSION = 1;
@@ -37739,7 +37918,7 @@ function isOwnedCliBridge(path, expectedPaths) {
37739
37918
  return false;
37740
37919
  return Object.entries(CLI_BRIDGE_FILES).every(([name, content]) => {
37741
37920
  const file = join11(path, name), stat = lstatSync6(file);
37742
- return stat.isFile() && !stat.isSymbolicLink() && stat.size === Buffer.byteLength(content) && readFileSync8(file, "utf8") === content;
37921
+ return stat.isFile() && !stat.isSymbolicLink() && stat.size === Buffer.byteLength(content) && readFileSync9(file, "utf8") === content;
37743
37922
  });
37744
37923
  } catch {
37745
37924
  return false;
@@ -37748,7 +37927,7 @@ function isOwnedCliBridge(path, expectedPaths) {
37748
37927
 
37749
37928
  // src/lib/agent-discovery.ts
37750
37929
  import { createHash as createHash15 } from "crypto";
37751
- import { lstatSync as lstatSync17, readFileSync as readFileSync12, readdirSync as readdirSync6, realpathSync as realpathSync3 } from "fs";
37930
+ import { lstatSync as lstatSync17, readFileSync as readFileSync13, readdirSync as readdirSync6, realpathSync as realpathSync3 } from "fs";
37752
37931
  import { basename as basename6, dirname as dirname13, isAbsolute as isAbsolute14, join as join20, resolve as resolve13, sep as sep3 } from "path";
37753
37932
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
37754
37933
 
@@ -37800,7 +37979,7 @@ var $visitAsync = visit.visitAsync;
37800
37979
 
37801
37980
  // src/lib/agent-hermes.ts
37802
37981
  import { dirname as dirname4, isAbsolute as isAbsolute4, join as join12, resolve as resolve4 } from "path";
37803
- import { lstatSync as lstatSync7, readFileSync as readFileSync9, opendirSync } from "fs";
37982
+ import { lstatSync as lstatSync7, readFileSync as readFileSync10, opendirSync } from "fs";
37804
37983
  var HERMES_OPT_OUT = ".no-bundled-skills";
37805
37984
  var EVENTS = ["pre_llm_call", "pre_tool_call"];
37806
37985
  function object3(value) {
@@ -37890,7 +38069,7 @@ function read(path) {
37890
38069
  return null;
37891
38070
  if (!stat.isFile() || stat.size > 1024 * 1024)
37892
38071
  throw new Error("NATIVE_SKILL_DRIFT: invalid Hermes protection input");
37893
- return readFileSync9(path, "utf8");
38072
+ return readFileSync10(path, "utf8");
37894
38073
  }
37895
38074
  function assertHermesProtection(home, config, command, profile, supervisor) {
37896
38075
  assertHermesEnvironment(home);
@@ -38146,7 +38325,7 @@ function hashRawDiscoveryFile(path, budget, changes) {
38146
38325
 
38147
38326
  // src/lib/agent-discovery-path-bytes.ts
38148
38327
  import { createHash as createHash8 } from "crypto";
38149
- import { lstatSync as lstatSync10, readlinkSync } from "fs";
38328
+ import { lstatSync as lstatSync10, readlinkSync as readlinkSync2 } from "fs";
38150
38329
  import { dirname as dirname7, isAbsolute as isAbsolute7, join as join14, parse as parse2, resolve as resolve7, sep as sep2 } from "path";
38151
38330
  function identity2(stat, mutable = false) {
38152
38331
  return {
@@ -38202,7 +38381,7 @@ function trace(path) {
38202
38381
  if (stat.isSymbolicLink()) {
38203
38382
  if (++links > AGENT_POLICY_LIMITS.discoveryPathLinks || stat.size > BigInt(AGENT_POLICY_LIMITS.pathCharacters))
38204
38383
  throw new Error("Discovery path link limit exceeded");
38205
- const rawTarget = readlinkSync(candidate, { encoding: "buffer" }), target = rawTarget.toString("utf8"), after = lstatSync10(candidate, { bigint: true });
38384
+ const rawTarget = readlinkSync2(candidate, { encoding: "buffer" }), target = rawTarget.toString("utf8"), after = lstatSync10(candidate, { bigint: true });
38206
38385
  if (!rawTarget.equals(Buffer.from(target, "utf8")))
38207
38386
  throw new Error("Unsupported non-UTF8 discovery link target");
38208
38387
  if (!target || target.includes("\x00") || Buffer.byteLength(target) > AGENT_POLICY_LIMITS.pathCharacters || !after.isSymbolicLink() || JSON.stringify(identity2(stat, true)) !== JSON.stringify(identity2(after, true)))
@@ -38832,11 +39011,11 @@ function pluginExecutableDigest(path) {
38832
39011
  }
38833
39012
 
38834
39013
  // src/lib/skill-validation.ts
38835
- import { existsSync as existsSync5, lstatSync as lstatSync12, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
39014
+ import { existsSync as existsSync5, lstatSync as lstatSync12, readFileSync as readFileSync12, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
38836
39015
  import { isAbsolute as isAbsolute9, join as join17, normalize } from "path";
38837
39016
 
38838
39017
  // src/lib/hosted-skill-set.ts
38839
- import { existsSync as existsSync4, readFileSync as readFileSync10, readdirSync as readdirSync4, statSync as statSync3 } from "fs";
39018
+ import { existsSync as existsSync4, readFileSync as readFileSync11, readdirSync as readdirSync4, statSync as statSync3 } from "fs";
38840
39019
  import { join as join16 } from "path";
38841
39020
  var HOSTED_RUNTIMES = new Set(["hosted"]);
38842
39021
  var HOSTED_SOURCES = new Set(["remote", "private-hosted"]);
@@ -38854,7 +39033,7 @@ function isHostedMetadataSkillDir(skillDir) {
38854
39033
  if (!existsSync4(pkgPath))
38855
39034
  return false;
38856
39035
  try {
38857
- return isHostedMetadataPackage(JSON.parse(readFileSync10(pkgPath, "utf8")));
39036
+ return isHostedMetadataPackage(JSON.parse(readFileSync11(pkgPath, "utf8")));
38858
39037
  } catch {
38859
39038
  return false;
38860
39039
  }
@@ -38928,7 +39107,7 @@ function add(target, code, message) {
38928
39107
  target.push({ code, message });
38929
39108
  }
38930
39109
  function readJsonFile(path) {
38931
- return JSON.parse(readFileSync11(path, "utf-8"));
39110
+ return JSON.parse(readFileSync12(path, "utf-8"));
38932
39111
  }
38933
39112
  function asRecord(value) {
38934
39113
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
@@ -39086,7 +39265,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39086
39265
  }
39087
39266
  const skillMdPath = join17(skillPath, "SKILL.md");
39088
39267
  if (existsSync5(skillMdPath)) {
39089
- const frontmatter = parseSkillFrontmatter(readFileSync11(skillMdPath, "utf-8"));
39268
+ const frontmatter = parseSkillFrontmatter(readFileSync12(skillMdPath, "utf-8"));
39090
39269
  if (!frontmatter) {
39091
39270
  add(warnings, "skill.frontmatter_missing", "SKILL.md has no YAML frontmatter");
39092
39271
  } else {
@@ -40387,7 +40566,7 @@ function read2(path, changes) {
40387
40566
  return null;
40388
40567
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
40389
40568
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
40390
- return readFileSync12(path, "utf8");
40569
+ return readFileSync13(path, "utf8");
40391
40570
  }
40392
40571
  function projected(source, changes, budget = discoveryByteBudget()) {
40393
40572
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
@@ -40893,7 +41072,7 @@ function readRootAlias(home, agent) {
40893
41072
  const stat2 = lstatSync18(alias, { throwIfNoEntry: false, bigint: true });
40894
41073
  if (!stat2?.isSymbolicLink())
40895
41074
  throw new Error(`Agent root alias changed after planning: ${alias}`);
40896
- const link = readlinkSync2(alias), targetPath = resolve14(dirname14(alias), link);
41075
+ const link = readlinkSync3(alias), targetPath = resolve14(dirname14(alias), link);
40897
41076
  assertSafePath(targetPath);
40898
41077
  const targetStat = lstatSync18(targetPath, { throwIfNoEntry: false });
40899
41078
  if (!targetStat?.isDirectory())
@@ -41001,8 +41180,8 @@ function selectNativeMigrationTargets(inventory, manifest) {
41001
41180
  if (matches.length !== 1)
41002
41181
  throw new Error(`Native migration target was not found exactly once: ${target.agent} ${target.projectRoot}/${target.path}`);
41003
41182
  const entry = matches[0];
41004
- if (entry.bridge || entry.system || entry.vendor)
41005
- throw new Error(`Native migration target is protected or vendor-owned: ${entry.path}`);
41183
+ if (entry.bridge || entry.system || entry.vendor !== (target.vendor === true))
41184
+ throw new Error(`Native migration target is protected or vendor classification changed: ${entry.path}`);
41006
41185
  if (entry.hash !== target.treeSha256 || treeHash(entry.path) !== target.treeSha256)
41007
41186
  throw new Error(`Native migration target changed after review: ${entry.path}`);
41008
41187
  selected.push(entry);
@@ -41025,6 +41204,8 @@ function projectAncestorDirectories(projects) {
41025
41204
  return [...directories];
41026
41205
  }
41027
41206
  function inventoryNativeSkills(home = homedir3(), options = {}) {
41207
+ if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute15(options.reviewedCacheAlias) || resolve14(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
41208
+ throw new Error("A reviewed cache alias requires vendor inventory and an exact absolute path");
41028
41209
  const aliases = rootAliases(home, options.allowRootAliases);
41029
41210
  const selectedAgents = options.agents ? new Set(options.agents) : undefined;
41030
41211
  const includesAgent = (agent) => !selectedAgents || selectedAgents.has(agent);
@@ -41045,14 +41226,22 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
41045
41226
  if (discoveryPathBytes > 4 * 1024 * 1024)
41046
41227
  throw new Error("Native skill discovery metadata limit exceeded");
41047
41228
  }
41048
- function emptySiblingCacheAlias(path, parent) {
41049
- const link = readlinkSync2(path), target = resolve14(parent, link);
41229
+ let reviewedCacheAliasFound = false;
41230
+ function verifiedSiblingCacheAlias(path, parent) {
41231
+ const link = readlinkSync3(path), target = resolve14(parent, link);
41050
41232
  if (dirname14(target) !== parent || (isAbsolute15(link) ? link !== target : dirname14(link) !== "."))
41051
41233
  return false;
41052
41234
  if (!lstatSync18(target, { throwIfNoEntry: false })?.isDirectory())
41053
41235
  return false;
41054
41236
  const scan = cacheScans.get(target);
41055
- return Boolean(scan?.complete && !scan.hasSkills && scan.entries <= maxAliasProofEntries);
41237
+ if (!scan?.complete || scan.entries > maxAliasProofEntries)
41238
+ return false;
41239
+ if (scan.hasSkills) {
41240
+ if (path !== options.reviewedCacheAlias)
41241
+ return false;
41242
+ reviewedCacheAliasFound = true;
41243
+ }
41244
+ return true;
41056
41245
  }
41057
41246
  function visit2(agent, path, vendor = false, depth = 0, pluginCache = false, admitted = false) {
41058
41247
  if (!admitted)
@@ -41075,7 +41264,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
41075
41264
  const marker = join21(path, ".hasna-skills.json");
41076
41265
  if (existsSync6(marker)) {
41077
41266
  try {
41078
- managed = JSON.parse(readFileSync13(marker, "utf8")).managedBy === "@hasna/skills";
41267
+ managed = JSON.parse(readFileSync14(marker, "utf8")).managedBy === "@hasna/skills";
41079
41268
  } catch {}
41080
41269
  }
41081
41270
  const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
@@ -41109,7 +41298,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
41109
41298
  const child = join21(path, name);
41110
41299
  if (isVendor && lstatSync18(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
41111
41300
  const target = statSync5(child, { throwIfNoEntry: false });
41112
- if (target?.isFile() || pluginCache && target?.isDirectory() && emptySiblingCacheAlias(child, path)) {
41301
+ if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(child, path)) {
41113
41302
  scan.entries++;
41114
41303
  continue;
41115
41304
  }
@@ -41143,12 +41332,14 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
41143
41332
  for (const root2 of [...options.agentRoots ?? [], ...configured])
41144
41333
  if (includesAgent(root2.agent))
41145
41334
  scanRoot(root2.agent, canonicalAgentPath(root2.path, aliases), true);
41335
+ if (options.reviewedCacheAlias !== undefined && !reviewedCacheAliasFound)
41336
+ throw new Error("Reviewed cache alias was not an inventoried skill-containing sibling alias");
41146
41337
  recheckRootAliases(aliases);
41147
41338
  return entries;
41148
41339
  }
41149
41340
  function readOptional(path) {
41150
41341
  assertSafePath(path);
41151
- return existsSync6(path) ? readFileSync13(path, "utf8") : null;
41342
+ return existsSync6(path) ? readFileSync14(path, "utf8") : null;
41152
41343
  }
41153
41344
  function jsonObject(text2, path) {
41154
41345
  if (text2 === null)
@@ -41862,7 +42053,7 @@ var SKILLS = [];
41862
42053
 
41863
42054
  // src/lib/skill-hash.ts
41864
42055
  import { createHash as createHash17 } from "crypto";
41865
- import { existsSync as existsSync7, readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync6 } from "fs";
42056
+ import { existsSync as existsSync7, readdirSync as readdirSync8, readFileSync as readFileSync15, statSync as statSync6 } from "fs";
41866
42057
  import { join as join22, sep as sep5 } from "path";
41867
42058
  var CONTENT_HASH_ALGORITHM = "sha256";
41868
42059
  var HASH_EXCLUDE_DIRS = new Set([".git", "node_modules", "dist", "build", ".turbo"]);
@@ -41959,7 +42150,7 @@ function collectDirectory(files, dir, rel) {
41959
42150
  }
41960
42151
  }
41961
42152
  function collectFile(files, absolute, rel) {
41962
- const buffer = readFileSync14(absolute);
42153
+ const buffer = readFileSync15(absolute);
41963
42154
  files.push(normalizeBundleFile(rel.split(sep5).join("/"), buffer));
41964
42155
  }
41965
42156
  function normalizeBundleFile(rel, buffer) {
@@ -42376,7 +42567,7 @@ import {
42376
42567
  existsSync as existsSync8,
42377
42568
  lstatSync as lstatSync19,
42378
42569
  mkdirSync as mkdirSync6,
42379
- readFileSync as readFileSync15,
42570
+ readFileSync as readFileSync16,
42380
42571
  realpathSync as realpathSync5,
42381
42572
  writeFileSync as writeFileSync5
42382
42573
  } from "fs";
@@ -42441,7 +42632,7 @@ function readManifest(skillPath, fallbackName, normalizeName) {
42441
42632
  const skillMdPath = join23(skillPath, "SKILL.md");
42442
42633
  const pkgPath = join23(skillPath, "package.json");
42443
42634
  const jsonManifest = existsSync8(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
42444
- const frontmatter = existsSync8(skillMdPath) ? parseSkillFrontmatter(readFileSync15(skillMdPath, "utf-8")) ?? undefined : undefined;
42635
+ const frontmatter = existsSync8(skillMdPath) ? parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8")) ?? undefined : undefined;
42445
42636
  const pkg = existsSync8(pkgPath) ? readJsonObject(pkgPath) : undefined;
42446
42637
  const name = normalizeName(stringField(jsonManifest, "name") ?? frontmatter?.name ?? stringValue(pkg?.name) ?? fallbackName);
42447
42638
  const description = stringField(jsonManifest, "description") ?? frontmatter?.description ?? stringValue(pkg?.description) ?? `${name} skill`;
@@ -42475,7 +42666,7 @@ function readDeclaredSkillVersion(skillPath) {
42475
42666
  const skillMdPath = join23(skillPath, "SKILL.md");
42476
42667
  const pkgPath = join23(skillPath, "package.json");
42477
42668
  const jsonManifest = existsSync8(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
42478
- const frontmatter = existsSync8(skillMdPath) ? parseSkillFrontmatter(readFileSync15(skillMdPath, "utf-8")) ?? undefined : undefined;
42669
+ const frontmatter = existsSync8(skillMdPath) ? parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8")) ?? undefined : undefined;
42479
42670
  const pkg = existsSync8(pkgPath) ? readJsonObject(pkgPath) : undefined;
42480
42671
  return stringField(jsonManifest, "version") ?? frontmatter?.version ?? stringValue(pkg?.version);
42481
42672
  }
@@ -42596,7 +42787,7 @@ function readExistingSkillJson(skillPath) {
42596
42787
  if (!existsSync8(path))
42597
42788
  return {};
42598
42789
  try {
42599
- const parsed = JSON.parse(readFileSync15(path, "utf-8"));
42790
+ const parsed = JSON.parse(readFileSync16(path, "utf-8"));
42600
42791
  return isRecord2(parsed) ? parsed : {};
42601
42792
  } catch {
42602
42793
  return {};
@@ -42633,7 +42824,7 @@ function ensurePortableSkillFiles(skillPath, manifest) {
42633
42824
  if (!existsSync8(join23(skillPath, "SKILL.md")))
42634
42825
  writeFileSync5(join23(skillPath, "SKILL.md"), renderSkillMd(next));
42635
42826
  else
42636
- writeFileSync5(join23(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync15(join23(skillPath, "SKILL.md"), "utf-8"), next));
42827
+ writeFileSync5(join23(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync16(join23(skillPath, "SKILL.md"), "utf-8"), next));
42637
42828
  if (!existsSync8(join23(skillPath, "AGENTS.md")))
42638
42829
  writeFileSync5(join23(skillPath, "AGENTS.md"), renderAgentsMd(next));
42639
42830
  ensurePackageJson(skillPath, next);
@@ -42694,7 +42885,7 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
42694
42885
  writeFileSync5(join23(skillPath, "SKILL.md"), renderSkillMd(next));
42695
42886
  } else {
42696
42887
  const path = join23(skillPath, "SKILL.md");
42697
- const content = readFileSync15(path, "utf8");
42888
+ const content = readFileSync16(path, "utf8");
42698
42889
  const declaredName = parseSkillFrontmatter(content)?.name;
42699
42890
  if (declaredName && declaredName !== next.name) {
42700
42891
  writeFileSync5(path, renameInstructionFrontmatter(content, next.name));
@@ -42986,7 +43177,7 @@ function inferRuntimeFromCommands(commands) {
42986
43177
  return { ...defaultRuntimeContract(entrypoint), runtime: "python3" };
42987
43178
  }
42988
43179
  function readJsonObject(path) {
42989
- const parsed = JSON.parse(readFileSync15(path, "utf-8"));
43180
+ const parsed = JSON.parse(readFileSync16(path, "utf-8"));
42990
43181
  if (!isRecord2(parsed))
42991
43182
  throw new Error(`${basename7(path)} must contain a JSON object`);
42992
43183
  return parsed;
@@ -43585,7 +43776,7 @@ function hasSkillsOwnershipMarker(dir) {
43585
43776
  try {
43586
43777
  if (!lstatSync21(path).isFile())
43587
43778
  return false;
43588
- const marker = JSON.parse(readFileSync16(path, "utf8"));
43779
+ const marker = JSON.parse(readFileSync17(path, "utf8"));
43589
43780
  return isSkillsOwnershipMarker(marker);
43590
43781
  } catch {
43591
43782
  return false;
@@ -43794,7 +43985,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
43794
43985
  if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
43795
43986
  let existingIsStub = false;
43796
43987
  try {
43797
- existingIsStub = isPointerSkillMd(readFileSync16(skillMdPath, "utf-8"));
43988
+ existingIsStub = isPointerSkillMd(readFileSync17(skillMdPath, "utf-8"));
43798
43989
  } catch {
43799
43990
  existingIsStub = false;
43800
43991
  }
@@ -43874,7 +44065,7 @@ function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = f
43874
44065
  if (kind === undefined || kind === "instruction" || preferBundledDocs) {
43875
44066
  const skillMdPath = join26(skillPath, "SKILL.md");
43876
44067
  if (existsSync10(skillMdPath))
43877
- return readFileSync16(skillMdPath, "utf-8");
44068
+ return readFileSync17(skillMdPath, "utf-8");
43878
44069
  }
43879
44070
  return pointerSkillMd(name, description);
43880
44071
  }
@@ -43904,7 +44095,7 @@ function normalizeSkillName(name) {
43904
44095
  }
43905
44096
 
43906
44097
  // src/lib/registry.ts
43907
- import { existsSync as existsSync11, readFileSync as readFileSync17, readdirSync as readdirSync11 } from "fs";
44098
+ import { existsSync as existsSync11, readFileSync as readFileSync18, readdirSync as readdirSync11 } from "fs";
43908
44099
  import { join as join27 } from "path";
43909
44100
 
43910
44101
  // src/lib/registry-merge.ts
@@ -44120,7 +44311,7 @@ function discoverSkillsInDir(dir, source = "custom") {
44120
44311
  continue;
44121
44312
  let content;
44122
44313
  try {
44123
- content = readFileSync17(skillMdPath, "utf-8");
44314
+ content = readFileSync18(skillMdPath, "utf-8");
44124
44315
  } catch {
44125
44316
  continue;
44126
44317
  }
@@ -44157,7 +44348,7 @@ function findExtensionSkillPath(name) {
44157
44348
  continue;
44158
44349
  let content;
44159
44350
  try {
44160
- content = readFileSync17(skillMdPath, "utf-8");
44351
+ content = readFileSync18(skillMdPath, "utf-8");
44161
44352
  } catch {
44162
44353
  continue;
44163
44354
  }
@@ -44222,7 +44413,7 @@ function getAllTags() {
44222
44413
  }
44223
44414
 
44224
44415
  // src/lib/project-state.ts
44225
- import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync18, writeFileSync as writeFileSync8 } from "fs";
44416
+ import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync19, writeFileSync as writeFileSync8 } from "fs";
44226
44417
  import { join as join28 } from "path";
44227
44418
  var VALID_PIN_SOURCES = [
44228
44419
  "official",
@@ -44248,7 +44439,7 @@ function loadProjectConfig(targetDir = process.cwd()) {
44248
44439
  if (!existsSync12(path))
44249
44440
  return null;
44250
44441
  try {
44251
- return normalizeProjectConfig(JSON.parse(readFileSync18(path, "utf-8")));
44442
+ return normalizeProjectConfig(JSON.parse(readFileSync19(path, "utf-8")));
44252
44443
  } catch {
44253
44444
  return null;
44254
44445
  }
@@ -44435,7 +44626,7 @@ function createLocalSkillManifest(name, generateSkillMd) {
44435
44626
  let skillMd = "";
44436
44627
  const skillMdPath = join29(sourcePath, "SKILL.md");
44437
44628
  if (existsSync13(skillMdPath)) {
44438
- skillMd = readFileSync19(skillMdPath, "utf-8");
44629
+ skillMd = readFileSync20(skillMdPath, "utf-8");
44439
44630
  } else if (generateSkillMd) {
44440
44631
  skillMd = generateSkillMd(name) ?? "";
44441
44632
  } else {
@@ -44554,7 +44745,7 @@ function resolveAgentSkillMd(name, generateSkillMd) {
44554
44745
  const sourcePath = getSkillPath(name);
44555
44746
  const skillMdPath = join29(sourcePath, "SKILL.md");
44556
44747
  if (existsSync13(skillMdPath))
44557
- return readFileSync19(skillMdPath, "utf-8");
44748
+ return readFileSync20(skillMdPath, "utf-8");
44558
44749
  if (generateSkillMd)
44559
44750
  return generateSkillMd(name);
44560
44751
  return generateMinimalSkillMd(name);
@@ -44610,14 +44801,14 @@ function readBundledSkillVersion(name) {
44610
44801
  if (!existsSync13(pkgPath))
44611
44802
  return "unknown";
44612
44803
  try {
44613
- const pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
44804
+ const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
44614
44805
  return pkg.version || "unknown";
44615
44806
  } catch {
44616
44807
  return "unknown";
44617
44808
  }
44618
44809
  }
44619
44810
  function readFileIfExists(path) {
44620
- return existsSync13(path) ? readFileSync19(path, "utf-8") : null;
44811
+ return existsSync13(path) ? readFileSync20(path, "utf-8") : null;
44621
44812
  }
44622
44813
  function loadProjectConfigCompat(targetDir) {
44623
44814
  return loadProjectConfig(targetDir);
@@ -44665,7 +44856,7 @@ function isInstructionSkillDir(skillPath, meta) {
44665
44856
  if (!existsSync14(skillMdPath))
44666
44857
  return false;
44667
44858
  try {
44668
- return parseSkillFrontmatter(readFileSync20(skillMdPath, "utf-8"))?.kind === "instruction";
44859
+ return parseSkillFrontmatter(readFileSync21(skillMdPath, "utf-8"))?.kind === "instruction";
44669
44860
  } catch {
44670
44861
  return false;
44671
44862
  }
@@ -44716,7 +44907,7 @@ function getSkillRequirements(name) {
44716
44907
  const meta = getSkill(name);
44717
44908
  let dependencies = {};
44718
44909
  try {
44719
- dependencies = JSON.parse(readFileSync20(join30(skillPath, "package.json"), "utf8")).dependencies || {};
44910
+ dependencies = JSON.parse(readFileSync21(join30(skillPath, "package.json"), "utf8")).dependencies || {};
44720
44911
  } catch {}
44721
44912
  return getSkillRequirementsFromContent(name, texts, dependencies, meta);
44722
44913
  }
@@ -44784,7 +44975,7 @@ async function runSkill(name, args, options = {}) {
44784
44975
  }
44785
44976
  let entryPoint2;
44786
44977
  try {
44787
- const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
44978
+ const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
44788
44979
  if (pkg.bin) {
44789
44980
  const binValues = Object.values(pkg.bin);
44790
44981
  entryPoint2 = binValues[0];
@@ -44887,7 +45078,7 @@ function generateSkillMd(name) {
44887
45078
  const pkgPath = join30(skillPath, "package.json");
44888
45079
  if (existsSync14(pkgPath)) {
44889
45080
  try {
44890
- const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
45081
+ const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
44891
45082
  if (pkg.bin) {
44892
45083
  const binKeys = Object.keys(pkg.bin);
44893
45084
  if (binKeys.length > 0)
@@ -44963,7 +45154,7 @@ function extractEnvVars(text2) {
44963
45154
  function readIfExists(path) {
44964
45155
  try {
44965
45156
  if (existsSync14(path)) {
44966
- return readFileSync20(path, "utf-8");
45157
+ return readFileSync21(path, "utf-8");
44967
45158
  }
44968
45159
  } catch {}
44969
45160
  return null;
@@ -55572,7 +55763,7 @@ class PostgresSkillSelectionStore {
55572
55763
 
55573
55764
  // src/server/sqlite-store.ts
55574
55765
  import { randomUUID as randomUUID7 } from "crypto";
55575
- import { mkdirSync as mkdirSync11, readFileSync as readFileSync22, readdirSync as readdirSync12 } from "fs";
55766
+ import { mkdirSync as mkdirSync11, readFileSync as readFileSync23, readdirSync as readdirSync12 } from "fs";
55576
55767
  import { dirname as dirname22, join as join35 } from "path";
55577
55768
 
55578
55769
  // src/server/auth.ts
@@ -56626,7 +56817,7 @@ function applySqliteMigrations(db, migrationsDir = resolveMigrationsDir("sqlite"
56626
56817
  const appliedNow = [];
56627
56818
  for (const file of files) {
56628
56819
  const version2 = file.replace(/\.sql$/, "");
56629
- const text2 = readFileSync22(join35(migrationsDir, file), "utf8");
56820
+ const text2 = readFileSync23(join35(migrationsDir, file), "utf8");
56630
56821
  const apply = db.transaction(() => {
56631
56822
  const already = db.query("SELECT 1 AS present FROM schema_migrations WHERE version = ? LIMIT 1").get(version2);
56632
56823
  if (already)
@@ -63255,15 +63446,11 @@ function resolveServerConfig(env = process.env) {
63255
63446
  requestBodyLimitBytes: parsePositiveInt(env.HASNA_SKILLS_REQUEST_BODY_LIMIT_BYTES, 1e6),
63256
63447
  skillBundleLimitBytes: parsePositiveInt(env.HASNA_SKILLS_BUNDLE_LIMIT_BYTES, 25000000),
63257
63448
  tombstoneWindowMs: parsePositiveInt(env.HASNA_SKILLS_TOMBSTONE_WINDOW_MS, 7 * 24 * 60 * 60 * 1000),
63258
- publicBaseUrl: (env.SKILLS_PUBLIC_BASE_URL || localOrigin(host, port)).replace(/\/+$/, ""),
63449
+ publicBaseUrl: (env.SKILLS_PUBLIC_BASE_URL || "").replace(/\/+$/, ""),
63259
63450
  nodeEnv,
63260
63451
  allowEphemeralStore: env.HASNA_SKILLS_ALLOW_EPHEMERAL_STORE === "1"
63261
63452
  };
63262
63453
  }
63263
- function localOrigin(host, port) {
63264
- const hostname = host === "0.0.0.0" || host === "::" ? "localhost" : host;
63265
- return `http://${hostname.includes(":") ? `[${hostname}]` : hostname}:${port}`;
63266
- }
63267
63454
  function parsePositiveInt(value, fallback) {
63268
63455
  const parsed = Number.parseInt(value ?? "", 10);
63269
63456
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
@@ -64533,6 +64720,9 @@ async function createSkillsFetchHandler(options = {}) {
64533
64720
  const config = { ...resolveServerConfig(), ...options.config };
64534
64721
  if (!options.store)
64535
64722
  assertDurableTarget(resolveDatabaseTarget(config.databaseUrl), config);
64723
+ if (!config.publicBaseUrl) {
64724
+ throw new Error("refusing to start: set SKILLS_PUBLIC_BASE_URL to this Skills server's public API origin; a bound socket is not an authority for client receipts.");
64725
+ }
64536
64726
  const store = options.store ?? await createStore({
64537
64727
  databaseUrl: config.databaseUrl,
64538
64728
  bootstrapApiKey: config.bootstrapApiKey
@@ -69448,7 +69638,7 @@ __export(exports_external2, {
69448
69638
  input: () => input,
69449
69639
  includes: () => _includes,
69450
69640
  httpUrl: () => httpUrl,
69451
- hostname: () => hostname2,
69641
+ hostname: () => hostname3,
69452
69642
  hex: () => hex2,
69453
69643
  hash: () => hash3,
69454
69644
  guid: () => guid2,
@@ -71234,7 +71424,7 @@ __export(exports_regexes, {
71234
71424
  idnEmail: () => idnEmail,
71235
71425
  httpProtocol: () => httpProtocol,
71236
71426
  html5Email: () => html5Email,
71237
- hostname: () => hostname,
71427
+ hostname: () => hostname2,
71238
71428
  hex: () => hex,
71239
71429
  guid: () => guid,
71240
71430
  extendedDuration: () => extendedDuration,
@@ -71296,7 +71486,7 @@ var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]
71296
71486
  var cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
71297
71487
  var base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
71298
71488
  var base64url = /^[A-Za-z0-9_-]*$/;
71299
- var hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
71489
+ var hostname2 = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
71300
71490
  var domain = /^(?=.{1,253}$)([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$/;
71301
71491
  var httpProtocol = /^https?$/;
71302
71492
  var e164 = /^\+[1-9]\d{6,14}$/;
@@ -72133,9 +72323,9 @@ var asciiTabOrNewline = /[\t\n\r]/g;
72133
72323
  function stripTabAndNewline(value) {
72134
72324
  return value.replace(asciiTabOrNewline, "");
72135
72325
  }
72136
- function urlHostnameOk(url, hostname2) {
72137
- hostname2.lastIndex = 0;
72138
- return hostname2.test(url.hostname);
72326
+ function urlHostnameOk(url, hostname3) {
72327
+ hostname3.lastIndex = 0;
72328
+ return hostname3.test(url.hostname);
72139
72329
  }
72140
72330
  function urlProtocolOk(url, protocol) {
72141
72331
  protocol.lastIndex = 0;
@@ -85523,7 +85713,7 @@ __export(exports_schemas2, {
85523
85713
  int: () => int,
85524
85714
  instanceof: () => _instanceof,
85525
85715
  httpUrl: () => httpUrl,
85526
- hostname: () => hostname2,
85716
+ hostname: () => hostname3,
85527
85717
  hex: () => hex2,
85528
85718
  hash: () => hash3,
85529
85719
  guid: () => guid2,
@@ -86233,7 +86423,7 @@ var ZodCustomStringFormat = /* @__PURE__ */ $constructor("ZodCustomStringFormat"
86233
86423
  function stringFormat(format, fnOrRegex, _params = {}) {
86234
86424
  return _stringFormat(ZodCustomStringFormat, format, fnOrRegex, _params);
86235
86425
  }
86236
- function hostname2(_params) {
86426
+ function hostname3(_params) {
86237
86427
  return _stringFormat(ZodCustomStringFormat, "hostname", exports_regexes.hostname, _params);
86238
86428
  }
86239
86429
  function hex2(_params) {