@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/README.md +46 -9
- package/bin/index.js +470 -160
- package/bin/mcp.js +229 -42
- package/bin/migrate.js +2 -6
- package/bin/server.js +5 -6
- package/bin/worker.js +2 -6
- package/dist/cli/commands/context.d.ts +1 -0
- package/dist/index.js +256 -65
- package/dist/lib/agent-integration.d.ts +2 -0
- package/dist/lib/selection-cache.d.ts +12 -0
- package/dist/lib/session-reconciliation.d.ts +7 -1
- package/dist/sdk/index.js +329 -139
- package/package.json +1 -1
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(
|
|
7176
|
+
function isValidHostname(hostname2) {
|
|
7177
7177
|
const hostPattern = /^[a-z0-9][a-z0-9.-]*[a-z0-9]$/;
|
|
7178
|
-
return hostPattern.test(
|
|
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 (!
|
|
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:"}//${
|
|
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 = (
|
|
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 =
|
|
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
|
|
9587
|
-
if (
|
|
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(
|
|
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}//${
|
|
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:
|
|
10132
|
-
const url = new URL(`${protocol2}//${
|
|
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(
|
|
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 ||
|
|
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(
|
|
14252
|
-
this.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
|
-
|
|
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}${
|
|
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
|
|
25342
|
-
if (
|
|
25343
|
-
|
|
25341
|
+
let hostname2 = request2.hostname ?? "";
|
|
25342
|
+
if (hostname2[0] === "[" && hostname2.endsWith("]")) {
|
|
25343
|
+
hostname2 = request2.hostname.slice(1, -1);
|
|
25344
25344
|
} else {
|
|
25345
|
-
|
|
25345
|
+
hostname2 = request2.hostname;
|
|
25346
25346
|
}
|
|
25347
25347
|
const nodeHttpsOptions = {
|
|
25348
25348
|
headers: request2.headers,
|
|
25349
|
-
host:
|
|
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}${
|
|
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
|
|
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] ??
|
|
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
|
|
31533
|
+
const hostname2 = normalizeHostname(url.hostname);
|
|
31534
31534
|
const allowlist = (policy.allowPrivateHosts ?? []).map((entry) => normalizeHostname(entry.toLowerCase()));
|
|
31535
|
-
if (allowlist.includes(
|
|
31536
|
-
const version22 = isIP3(
|
|
31535
|
+
if (allowlist.includes(hostname2)) {
|
|
31536
|
+
const version22 = isIP3(hostname2);
|
|
31537
31537
|
if (version22 === 4 || version22 === 6) {
|
|
31538
|
-
return { hostname, addresses: [
|
|
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(
|
|
31543
|
+
resolved2 = await lookup2(hostname2);
|
|
31544
31544
|
} catch {
|
|
31545
|
-
throw new Error(`Webhook target ${
|
|
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 ${
|
|
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(
|
|
31553
|
+
const version2 = isIP3(hostname2);
|
|
31554
31554
|
if (version2 === 4 || version2 === 6) {
|
|
31555
|
-
if (isPrivateAddress(
|
|
31556
|
-
throw new Error(`Webhook target ${
|
|
31555
|
+
if (isPrivateAddress(hostname2)) {
|
|
31556
|
+
throw new Error(`Webhook target ${hostname2} is a private or special-use address`);
|
|
31557
31557
|
}
|
|
31558
|
-
return { hostname, addresses: [
|
|
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(
|
|
31563
|
+
resolved = await lookup(hostname2);
|
|
31564
31564
|
} catch {
|
|
31565
|
-
throw new Error(`Webhook target ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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(
|
|
31595
|
-
const lower =
|
|
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: (
|
|
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 (
|
|
32295
|
-
return dnsLookup(
|
|
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.
|
|
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 {
|
|
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
|
|
35212
|
-
throw
|
|
35213
|
-
|
|
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
|
-
|
|
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
|
|
35345
|
-
import { closeSync as closeSync6, fstatSync as fstatSync6, openSync as openSync6, readFileSync as
|
|
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 =
|
|
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 =
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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) &&
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
41049
|
-
|
|
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
|
-
|
|
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(
|
|
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() &&
|
|
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) ?
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
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(
|
|
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) ?
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
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 ||
|
|
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: () =>
|
|
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: () =>
|
|
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
|
|
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,
|
|
72137
|
-
|
|
72138
|
-
return
|
|
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: () =>
|
|
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
|
|
86426
|
+
function hostname3(_params) {
|
|
86237
86427
|
return _stringFormat(ZodCustomStringFormat, "hostname", exports_regexes.hostname, _params);
|
|
86238
86428
|
}
|
|
86239
86429
|
function hex2(_params) {
|