@hasna/skills 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +269 -14
- package/bin/index.js +7835 -5440
- package/bin/mcp.js +2040 -589
- package/bin/migrate.js +148 -40
- package/bin/server.js +66 -87
- package/bin/worker.js +42 -75
- package/dist/admin-contract.d.ts +37 -19
- package/dist/admin-contract.js +1 -1
- package/dist/cli/cli.test-utils.d.ts +10 -8
- package/dist/cli/commands/customer-profile.d.ts +2 -0
- package/dist/cli/commands/customer-verification.d.ts +5 -0
- package/dist/cli/commands/remote-account.d.ts +7 -0
- package/dist/cli/commands/tool-primitives.d.ts +1 -1
- package/dist/cli/commands/workspace-member-mutations.d.ts +2 -0
- package/dist/cli/commands/workspace-members.d.ts +2 -0
- package/dist/cli/env-assignment.d.ts +9 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +1369 -349
- package/dist/lib/agent-sync.d.ts +13 -8
- package/dist/lib/api-url.d.ts +4 -3
- package/dist/lib/app-home.d.ts +0 -1
- package/dist/lib/auth-store.d.ts +1 -1
- package/dist/lib/client-types.d.ts +75 -0
- package/dist/lib/credential-state.d.ts +12 -0
- package/dist/lib/fleet-credentials.d.ts +49 -17
- package/dist/lib/home-adoption.d.ts +2 -0
- package/dist/lib/home-census.d.ts +3 -1
- package/dist/lib/instance-credentials.d.ts +13 -0
- package/dist/lib/local-opt-in.d.ts +24 -0
- package/dist/lib/mcp-contracts.d.ts +4 -0
- package/dist/lib/portable-skills-files.d.ts +10 -2
- package/dist/lib/portable-skills-types.d.ts +2 -0
- package/dist/lib/read-access.d.ts +83 -0
- package/dist/lib/remote-account.d.ts +42 -0
- package/dist/lib/remote-auth.d.ts +46 -0
- package/dist/lib/remote-client.d.ts +90 -6
- package/dist/lib/remote-customer-operations.d.ts +106 -0
- package/dist/lib/remote-files.d.ts +21 -0
- package/dist/lib/remote-profile.d.ts +26 -0
- package/dist/lib/remote-registry.d.ts +7 -3
- package/dist/lib/remote-workspace.d.ts +76 -0
- package/dist/lib/run-routing.d.ts +1 -0
- package/dist/lib/run-state.d.ts +3 -0
- package/dist/lib/skillinfo.d.ts +1 -1
- package/dist/mcp/helpers.d.ts +22 -0
- package/dist/mcp/index.d.ts +16 -0
- package/dist/mcp/remote-customer-tools.d.ts +2 -0
- package/dist/sdk/governance-store.d.ts +1 -0
- package/dist/sdk/index.d.ts +8 -1
- package/dist/sdk/index.js +1994 -416
- package/dist/sdk/outputs.d.ts +0 -11
- package/dist/sdk/runs.d.ts +5 -5
- package/dist/storage.js +6 -40
- package/docs/skill-standard.md +30 -2
- package/package.json +7 -6
package/dist/sdk/index.js
CHANGED
|
@@ -2370,11 +2370,11 @@ var require_config = __commonJS((exports) => {
|
|
|
2370
2370
|
};
|
|
2371
2371
|
function getSelectorName(functionString) {
|
|
2372
2372
|
try {
|
|
2373
|
-
const
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
return [...
|
|
2373
|
+
const constants2 = new Set(Array.from(functionString.match(/([A-Z_]){3,}/g) ?? []));
|
|
2374
|
+
constants2.delete("CONFIG");
|
|
2375
|
+
constants2.delete("CONFIG_PREFIX_SEPARATOR");
|
|
2376
|
+
constants2.delete("ENV");
|
|
2377
|
+
return [...constants2].join(", ");
|
|
2378
2378
|
} catch (ignored) {
|
|
2379
2379
|
return functionString;
|
|
2380
2380
|
}
|
|
@@ -3573,7 +3573,7 @@ var require_serde = __commonJS((exports) => {
|
|
|
3573
3573
|
var { createHmac: createHmac2, createHash: createHash2, getRandomValues } = __require("crypto");
|
|
3574
3574
|
var { hasOwn: hasOwn2, HttpResponse } = require_transport();
|
|
3575
3575
|
exports.hasOwn = hasOwn2;
|
|
3576
|
-
var { ReadStream, lstatSync, fstatSync:
|
|
3576
|
+
var { ReadStream, lstatSync: lstatSync2, fstatSync: fstatSync3 } = __require("fs");
|
|
3577
3577
|
var { toEndpointV1 } = require_endpoints();
|
|
3578
3578
|
var { Readable, Writable, PassThrough } = __require("stream");
|
|
3579
3579
|
var isArrayBuffer = (arg) => typeof ArrayBuffer === "function" && arg instanceof ArrayBuffer || Object.prototype.toString.call(arg) === "[object ArrayBuffer]";
|
|
@@ -4339,9 +4339,9 @@ var require_serde = __commonJS((exports) => {
|
|
|
4339
4339
|
return body.end + 1 - body.start;
|
|
4340
4340
|
} else if (body instanceof ReadStream) {
|
|
4341
4341
|
if (body.path != null) {
|
|
4342
|
-
return
|
|
4342
|
+
return lstatSync2(body.path).size;
|
|
4343
4343
|
} else if (typeof body.fd === "number") {
|
|
4344
|
-
return
|
|
4344
|
+
return fstatSync3(body.fd).size;
|
|
4345
4345
|
}
|
|
4346
4346
|
}
|
|
4347
4347
|
throw new Error(`Body Length computation failed for ${body}`);
|
|
@@ -17645,7 +17645,7 @@ var require_httpAuthSchemes = __commonJS((exports) => {
|
|
|
17645
17645
|
});
|
|
17646
17646
|
|
|
17647
17647
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-env@3.972.70/node_modules/@aws-sdk/credential-provider-env/dist-es/fromEnv.js
|
|
17648
|
-
var
|
|
17648
|
+
var import_client8, import_config, ENV_KEY = "AWS_ACCESS_KEY_ID", ENV_SECRET = "AWS_SECRET_ACCESS_KEY", ENV_SESSION = "AWS_SESSION_TOKEN", ENV_EXPIRATION = "AWS_CREDENTIAL_EXPIRATION", ENV_CREDENTIAL_SCOPE = "AWS_CREDENTIAL_SCOPE", ENV_ACCOUNT_ID = "AWS_ACCOUNT_ID", fromEnv = (init) => async () => {
|
|
17649
17649
|
init?.logger?.debug("@aws-sdk/credential-provider-env - fromEnv");
|
|
17650
17650
|
const accessKeyId = process.env[ENV_KEY];
|
|
17651
17651
|
const secretAccessKey = process.env[ENV_SECRET];
|
|
@@ -17662,13 +17662,13 @@ var import_client6, import_config, ENV_KEY = "AWS_ACCESS_KEY_ID", ENV_SECRET = "
|
|
|
17662
17662
|
...credentialScope && { credentialScope },
|
|
17663
17663
|
...accountId && { accountId }
|
|
17664
17664
|
};
|
|
17665
|
-
|
|
17665
|
+
import_client8.setCredentialFeature(credentials, "CREDENTIALS_ENV_VARS", "g");
|
|
17666
17666
|
return credentials;
|
|
17667
17667
|
}
|
|
17668
17668
|
throw new import_config.CredentialsProviderError("Unable to find environment variable credentials.", { logger: init?.logger });
|
|
17669
17669
|
};
|
|
17670
17670
|
var init_fromEnv = __esm(() => {
|
|
17671
|
-
|
|
17671
|
+
import_client8 = __toESM(require_client2(), 1);
|
|
17672
17672
|
import_config = __toESM(require_config(), 1);
|
|
17673
17673
|
});
|
|
17674
17674
|
|
|
@@ -18738,7 +18738,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
18738
18738
|
return this.connectOptions === undefined ? http2.connect(url) : http2.connect(url, this.connectOptions);
|
|
18739
18739
|
}
|
|
18740
18740
|
}
|
|
18741
|
-
var { constants } = http2;
|
|
18741
|
+
var { constants: constants2 } = http2;
|
|
18742
18742
|
|
|
18743
18743
|
class NodeHttp2Handler {
|
|
18744
18744
|
config;
|
|
@@ -18829,8 +18829,8 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
18829
18829
|
}
|
|
18830
18830
|
const clientHttp2Stream = session.request({
|
|
18831
18831
|
...request.headers,
|
|
18832
|
-
[
|
|
18833
|
-
[
|
|
18832
|
+
[constants2.HTTP2_HEADER_PATH]: path,
|
|
18833
|
+
[constants2.HTTP2_HEADER_METHOD]: method
|
|
18834
18834
|
});
|
|
18835
18835
|
if (effectiveRequestTimeout) {
|
|
18836
18836
|
clientHttp2Stream.setTimeout(effectiveRequestTimeout, () => {
|
|
@@ -19010,7 +19010,7 @@ var retryWrapper = (toRetry, maxRetries, delayMs) => {
|
|
|
19010
19010
|
|
|
19011
19011
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-http@3.972.72/node_modules/@aws-sdk/credential-provider-http/dist-es/fromHttp/fromHttp.js
|
|
19012
19012
|
import fs from "fs/promises";
|
|
19013
|
-
var
|
|
19013
|
+
var import_client9, import_config9, import_node_http_handler, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", DEFAULT_LINK_LOCAL_HOST = "http://169.254.170.2", AWS_CONTAINER_CREDENTIALS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI", AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE = "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE", AWS_CONTAINER_AUTHORIZATION_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN", fromHttp = (options = {}) => {
|
|
19014
19014
|
options.logger?.debug("@aws-sdk/credential-provider-http - fromHttp");
|
|
19015
19015
|
let host;
|
|
19016
19016
|
const relative2 = options.awsContainerCredentialsRelativeUri ?? process.env[AWS_CONTAINER_CREDENTIALS_RELATIVE_URI];
|
|
@@ -19047,7 +19047,7 @@ Set AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
|
|
|
19047
19047
|
}
|
|
19048
19048
|
try {
|
|
19049
19049
|
const result = await requestHandler.handle(request, { requestTimeout });
|
|
19050
|
-
return getCredentials(result.response).then((creds) =>
|
|
19050
|
+
return getCredentials(result.response).then((creds) => import_client9.setCredentialFeature(creds, "CREDENTIALS_HTTP", "z"));
|
|
19051
19051
|
} catch (e2) {
|
|
19052
19052
|
throw new import_config9.CredentialsProviderError(String(e2), { logger: options.logger });
|
|
19053
19053
|
}
|
|
@@ -19069,7 +19069,7 @@ Set AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
|
|
|
19069
19069
|
var init_fromHttp = __esm(() => {
|
|
19070
19070
|
init_checkUrl();
|
|
19071
19071
|
init_requestHelpers();
|
|
19072
|
-
|
|
19072
|
+
import_client9 = __toESM(require_client2(), 1);
|
|
19073
19073
|
import_config9 = __toESM(require_config(), 1);
|
|
19074
19074
|
import_node_http_handler = __toESM(require_dist_cjs6(), 1);
|
|
19075
19075
|
});
|
|
@@ -20453,7 +20453,7 @@ var init_loadSso = __esm(() => {
|
|
|
20453
20453
|
});
|
|
20454
20454
|
|
|
20455
20455
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-sso@3.973.14/node_modules/@aws-sdk/credential-provider-sso/dist-es/resolveSSOCredentials.js
|
|
20456
|
-
var
|
|
20456
|
+
var import_client10, import_config15, SHOULD_FAIL_CREDENTIAL_CHAIN = false, resolveSSOCredentials = async ({ ssoStartUrl, ssoSession, ssoAccountId, ssoRegion, ssoRoleName, ssoClient, clientConfig, parentClientConfig, callerClientConfig, profile, filepath, configFilepath, ignoreCache, logger }) => {
|
|
20457
20457
|
let token;
|
|
20458
20458
|
const refreshMessage = `To refresh this SSO session run aws sso login with the corresponding profile.`;
|
|
20459
20459
|
if (ssoSession) {
|
|
@@ -20529,15 +20529,15 @@ var import_client8, import_config15, SHOULD_FAIL_CREDENTIAL_CHAIN = false, resol
|
|
|
20529
20529
|
...accountId && { accountId }
|
|
20530
20530
|
};
|
|
20531
20531
|
if (ssoSession) {
|
|
20532
|
-
|
|
20532
|
+
import_client10.setCredentialFeature(credentials, "CREDENTIALS_SSO", "s");
|
|
20533
20533
|
} else {
|
|
20534
|
-
|
|
20534
|
+
import_client10.setCredentialFeature(credentials, "CREDENTIALS_SSO_LEGACY", "u");
|
|
20535
20535
|
}
|
|
20536
20536
|
return credentials;
|
|
20537
20537
|
};
|
|
20538
20538
|
var init_resolveSSOCredentials = __esm(() => {
|
|
20539
20539
|
init_dist_es4();
|
|
20540
|
-
|
|
20540
|
+
import_client10 = __toESM(require_client2(), 1);
|
|
20541
20541
|
import_config15 = __toESM(require_config(), 1);
|
|
20542
20542
|
});
|
|
20543
20543
|
|
|
@@ -20649,7 +20649,7 @@ var init_dist_es5 = __esm(() => {
|
|
|
20649
20649
|
});
|
|
20650
20650
|
|
|
20651
20651
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-ini@3.973.15/node_modules/@aws-sdk/credential-provider-ini/dist-es/resolveCredentialSource.js
|
|
20652
|
-
var
|
|
20652
|
+
var import_client11, import_config18, resolveCredentialSource = (credentialSource, profileName, logger) => {
|
|
20653
20653
|
const sourceProvidersMap = {
|
|
20654
20654
|
EcsContainer: async (options) => {
|
|
20655
20655
|
const { fromHttp: fromHttp2 } = await Promise.resolve().then(() => (init_dist_es3(), exports_dist_es3));
|
|
@@ -20673,9 +20673,9 @@ var import_client9, import_config18, resolveCredentialSource = (credentialSource
|
|
|
20673
20673
|
} else {
|
|
20674
20674
|
throw new import_config18.CredentialsProviderError(`Unsupported credential source in profile ${profileName}. Got ${credentialSource}, expected EcsContainer or Ec2InstanceMetadata or Environment.`, { logger });
|
|
20675
20675
|
}
|
|
20676
|
-
}, setNamedProvider = (creds) =>
|
|
20676
|
+
}, setNamedProvider = (creds) => import_client11.setCredentialFeature(creds, "CREDENTIALS_PROFILE_NAMED_PROVIDER", "p");
|
|
20677
20677
|
var init_resolveCredentialSource = __esm(() => {
|
|
20678
|
-
|
|
20678
|
+
import_client11 = __toESM(require_client2(), 1);
|
|
20679
20679
|
import_config18 = __toESM(require_config(), 1);
|
|
20680
20680
|
});
|
|
20681
20681
|
|
|
@@ -21702,7 +21702,7 @@ var require_sts = __commonJS((exports) => {
|
|
|
21702
21702
|
});
|
|
21703
21703
|
|
|
21704
21704
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-ini@3.973.15/node_modules/@aws-sdk/credential-provider-ini/dist-es/resolveAssumeRoleCredentials.js
|
|
21705
|
-
var
|
|
21705
|
+
var import_client12, import_config19, isAssumeRoleProfile = (arg, { profile = "default", logger } = {}) => {
|
|
21706
21706
|
return Boolean(arg) && typeof arg === "object" && typeof arg.role_arn === "string" && ["undefined", "string"].indexOf(typeof arg.role_session_name) > -1 && ["undefined", "string"].indexOf(typeof arg.external_id) > -1 && ["undefined", "string"].indexOf(typeof arg.mfa_serial) > -1 && (isAssumeRoleWithSourceProfile(arg, { profile, logger }) || isCredentialSourceProfile(arg, { profile, logger }));
|
|
21707
21707
|
}, isAssumeRoleWithSourceProfile = (arg, { profile, logger }) => {
|
|
21708
21708
|
const withSourceProfile = typeof arg.source_profile === "string" && typeof arg.credential_source === "undefined";
|
|
@@ -21741,7 +21741,7 @@ var import_client10, import_config19, isAssumeRoleProfile = (arg, { profile = "d
|
|
|
21741
21741
|
[source_profile]: true
|
|
21742
21742
|
}, isCredentialSourceWithoutRoleArn(profiles[source_profile] ?? {})) : (await resolveCredentialSource(profileData.credential_source, profileName, options.logger)(options))();
|
|
21743
21743
|
if (isCredentialSourceWithoutRoleArn(profileData)) {
|
|
21744
|
-
return sourceCredsProvider.then((creds) =>
|
|
21744
|
+
return sourceCredsProvider.then((creds) => import_client12.setCredentialFeature(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o"));
|
|
21745
21745
|
} else {
|
|
21746
21746
|
const params = {
|
|
21747
21747
|
RoleArn: profileData.role_arn,
|
|
@@ -21758,14 +21758,14 @@ var import_client10, import_config19, isAssumeRoleProfile = (arg, { profile = "d
|
|
|
21758
21758
|
params.TokenCode = await options.mfaCodeProvider(mfa_serial);
|
|
21759
21759
|
}
|
|
21760
21760
|
const sourceCreds = await sourceCredsProvider;
|
|
21761
|
-
return options.roleAssumer(sourceCreds, params).then((creds) =>
|
|
21761
|
+
return options.roleAssumer(sourceCreds, params).then((creds) => import_client12.setCredentialFeature(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o"));
|
|
21762
21762
|
}
|
|
21763
21763
|
}, isCredentialSourceWithoutRoleArn = (section) => {
|
|
21764
21764
|
return !section.role_arn && !!section.credential_source;
|
|
21765
21765
|
};
|
|
21766
21766
|
var init_resolveAssumeRoleCredentials = __esm(() => {
|
|
21767
21767
|
init_resolveCredentialSource();
|
|
21768
|
-
|
|
21768
|
+
import_client12 = __toESM(require_client2(), 1);
|
|
21769
21769
|
import_config19 = __toESM(require_config(), 1);
|
|
21770
21770
|
});
|
|
21771
21771
|
|
|
@@ -22766,7 +22766,7 @@ var init_LoginCredentialsFetcher = __esm(() => {
|
|
|
22766
22766
|
});
|
|
22767
22767
|
|
|
22768
22768
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-login@3.972.77/node_modules/@aws-sdk/credential-provider-login/dist-es/fromLoginCredentials.js
|
|
22769
|
-
var
|
|
22769
|
+
var import_client13, import_config21, fromLoginCredentials = (init) => async ({ callerClientConfig } = {}) => {
|
|
22770
22770
|
init?.logger?.debug?.("@aws-sdk/credential-providers - fromLoginCredentials");
|
|
22771
22771
|
const profiles = await import_config21.parseKnownFiles(init || {});
|
|
22772
22772
|
const profileName = import_config21.getProfileName({
|
|
@@ -22781,11 +22781,11 @@ var import_client11, import_config21, fromLoginCredentials = (init) => async ({
|
|
|
22781
22781
|
}
|
|
22782
22782
|
const fetcher = new LoginCredentialsFetcher(profile, init, callerClientConfig);
|
|
22783
22783
|
const credentials = await fetcher.loadCredentials();
|
|
22784
|
-
return
|
|
22784
|
+
return import_client13.setCredentialFeature(credentials, "CREDENTIALS_LOGIN", "AD");
|
|
22785
22785
|
};
|
|
22786
22786
|
var init_fromLoginCredentials = __esm(() => {
|
|
22787
22787
|
init_LoginCredentialsFetcher();
|
|
22788
|
-
|
|
22788
|
+
import_client13 = __toESM(require_client2(), 1);
|
|
22789
22789
|
import_config21 = __toESM(require_config(), 1);
|
|
22790
22790
|
});
|
|
22791
22791
|
|
|
@@ -22799,7 +22799,7 @@ var init_dist_es6 = __esm(() => {
|
|
|
22799
22799
|
});
|
|
22800
22800
|
|
|
22801
22801
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-ini@3.973.15/node_modules/@aws-sdk/credential-provider-ini/dist-es/resolveLoginCredentials.js
|
|
22802
|
-
var
|
|
22802
|
+
var import_client14, isLoginProfile = (data) => {
|
|
22803
22803
|
return Boolean(data && data.login_session);
|
|
22804
22804
|
}, resolveLoginCredentials = async (profileName, options, callerClientConfig) => {
|
|
22805
22805
|
const { fromLoginCredentials: fromLoginCredentials2 } = await Promise.resolve().then(() => (init_dist_es6(), exports_dist_es5));
|
|
@@ -22807,14 +22807,14 @@ var import_client12, isLoginProfile = (data) => {
|
|
|
22807
22807
|
...options,
|
|
22808
22808
|
profile: profileName
|
|
22809
22809
|
})({ callerClientConfig });
|
|
22810
|
-
return
|
|
22810
|
+
return import_client14.setCredentialFeature(credentials, "CREDENTIALS_PROFILE_LOGIN", "AC");
|
|
22811
22811
|
};
|
|
22812
22812
|
var init_resolveLoginCredentials = __esm(() => {
|
|
22813
|
-
|
|
22813
|
+
import_client14 = __toESM(require_client2(), 1);
|
|
22814
22814
|
});
|
|
22815
22815
|
|
|
22816
22816
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-process@3.972.70/node_modules/@aws-sdk/credential-provider-process/dist-es/getValidatedProcessCredentials.js
|
|
22817
|
-
var
|
|
22817
|
+
var import_client15, getValidatedProcessCredentials = (profileName, data, profiles) => {
|
|
22818
22818
|
if (data.Version !== 1) {
|
|
22819
22819
|
throw Error(`Profile ${profileName} credential_process did not return Version 1.`);
|
|
22820
22820
|
}
|
|
@@ -22840,11 +22840,11 @@ var import_client13, getValidatedProcessCredentials = (profileName, data, profil
|
|
|
22840
22840
|
...data.CredentialScope && { credentialScope: data.CredentialScope },
|
|
22841
22841
|
...accountId && { accountId }
|
|
22842
22842
|
};
|
|
22843
|
-
|
|
22843
|
+
import_client15.setCredentialFeature(credentials, "CREDENTIALS_PROCESS", "w");
|
|
22844
22844
|
return credentials;
|
|
22845
22845
|
};
|
|
22846
22846
|
var init_getValidatedProcessCredentials = __esm(() => {
|
|
22847
|
-
|
|
22847
|
+
import_client15 = __toESM(require_client2(), 1);
|
|
22848
22848
|
});
|
|
22849
22849
|
|
|
22850
22850
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-process@3.972.70/node_modules/@aws-sdk/credential-provider-process/dist-es/resolveProcessCredentials.js
|
|
@@ -22905,20 +22905,20 @@ var init_dist_es7 = __esm(() => {
|
|
|
22905
22905
|
});
|
|
22906
22906
|
|
|
22907
22907
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-ini@3.973.15/node_modules/@aws-sdk/credential-provider-ini/dist-es/resolveProcessCredentials.js
|
|
22908
|
-
var
|
|
22908
|
+
var import_client16, isProcessProfile = (arg) => Boolean(arg) && typeof arg === "object" && typeof arg.credential_process === "string", resolveProcessCredentials2 = async (options, profile) => {
|
|
22909
22909
|
const { fromProcess: fromProcess2 } = await Promise.resolve().then(() => (init_dist_es7(), exports_dist_es6));
|
|
22910
22910
|
const credentials = await fromProcess2({
|
|
22911
22911
|
...options,
|
|
22912
22912
|
profile
|
|
22913
22913
|
})();
|
|
22914
|
-
return
|
|
22914
|
+
return import_client16.setCredentialFeature(credentials, "CREDENTIALS_PROFILE_PROCESS", "v");
|
|
22915
22915
|
};
|
|
22916
22916
|
var init_resolveProcessCredentials2 = __esm(() => {
|
|
22917
|
-
|
|
22917
|
+
import_client16 = __toESM(require_client2(), 1);
|
|
22918
22918
|
});
|
|
22919
22919
|
|
|
22920
22920
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-ini@3.973.15/node_modules/@aws-sdk/credential-provider-ini/dist-es/resolveSsoCredentials.js
|
|
22921
|
-
var
|
|
22921
|
+
var import_client17, resolveSsoCredentials = async (profile, profileData, options = {}, callerClientConfig) => {
|
|
22922
22922
|
const { fromSSO: fromSSO2 } = await Promise.resolve().then(() => (init_dist_es5(), exports_dist_es4));
|
|
22923
22923
|
return fromSSO2({
|
|
22924
22924
|
profile,
|
|
@@ -22929,18 +22929,18 @@ var import_client15, resolveSsoCredentials = async (profile, profileData, option
|
|
|
22929
22929
|
callerClientConfig
|
|
22930
22930
|
}).then((creds) => {
|
|
22931
22931
|
if (profileData.sso_session) {
|
|
22932
|
-
return
|
|
22932
|
+
return import_client17.setCredentialFeature(creds, "CREDENTIALS_PROFILE_SSO", "r");
|
|
22933
22933
|
} else {
|
|
22934
|
-
return
|
|
22934
|
+
return import_client17.setCredentialFeature(creds, "CREDENTIALS_PROFILE_SSO_LEGACY", "t");
|
|
22935
22935
|
}
|
|
22936
22936
|
});
|
|
22937
22937
|
}, isSsoProfile2 = (arg) => arg && (typeof arg.sso_start_url === "string" || typeof arg.sso_account_id === "string" || typeof arg.sso_session === "string" || typeof arg.sso_region === "string" || typeof arg.sso_role_name === "string");
|
|
22938
22938
|
var init_resolveSsoCredentials = __esm(() => {
|
|
22939
|
-
|
|
22939
|
+
import_client17 = __toESM(require_client2(), 1);
|
|
22940
22940
|
});
|
|
22941
22941
|
|
|
22942
22942
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-ini@3.973.15/node_modules/@aws-sdk/credential-provider-ini/dist-es/resolveStaticCredentials.js
|
|
22943
|
-
var
|
|
22943
|
+
var import_client18, isStaticCredsProfile = (arg) => Boolean(arg) && typeof arg === "object" && typeof arg.aws_access_key_id === "string" && typeof arg.aws_secret_access_key === "string" && ["undefined", "string"].indexOf(typeof arg.aws_session_token) > -1 && ["undefined", "string"].indexOf(typeof arg.aws_account_id) > -1, resolveStaticCredentials = async (profile, options) => {
|
|
22944
22944
|
options?.logger?.debug("@aws-sdk/credential-provider-ini - resolveStaticCredentials");
|
|
22945
22945
|
const credentials = {
|
|
22946
22946
|
accessKeyId: profile.aws_access_key_id,
|
|
@@ -22949,10 +22949,10 @@ var import_client16, isStaticCredsProfile = (arg) => Boolean(arg) && typeof arg
|
|
|
22949
22949
|
...profile.aws_credential_scope && { credentialScope: profile.aws_credential_scope },
|
|
22950
22950
|
...profile.aws_account_id && { accountId: profile.aws_account_id }
|
|
22951
22951
|
};
|
|
22952
|
-
return
|
|
22952
|
+
return import_client18.setCredentialFeature(credentials, "CREDENTIALS_PROFILE", "n");
|
|
22953
22953
|
};
|
|
22954
22954
|
var init_resolveStaticCredentials = __esm(() => {
|
|
22955
|
-
|
|
22955
|
+
import_client18 = __toESM(require_client2(), 1);
|
|
22956
22956
|
});
|
|
22957
22957
|
|
|
22958
22958
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-web-identity@3.972.76/node_modules/@aws-sdk/credential-provider-web-identity/dist-es/fromWebToken.js
|
|
@@ -22984,7 +22984,7 @@ var fromWebToken = (init) => async (awsIdentityProperties) => {
|
|
|
22984
22984
|
|
|
22985
22985
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-web-identity@3.972.76/node_modules/@aws-sdk/credential-provider-web-identity/dist-es/fromTokenFile.js
|
|
22986
22986
|
import { readFileSync as readFileSync3 } from "fs";
|
|
22987
|
-
var
|
|
22987
|
+
var import_client19, import_config24, 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) => {
|
|
22988
22988
|
init.logger?.debug("@aws-sdk/credential-provider-web-identity - fromTokenFile");
|
|
22989
22989
|
const webIdentityTokenFile = init?.webIdentityTokenFile ?? process.env[ENV_TOKEN_FILE];
|
|
22990
22990
|
const roleArn = init?.roleArn ?? process.env[ENV_ROLE_ARN];
|
|
@@ -23001,12 +23001,12 @@ var import_client17, import_config24, ENV_TOKEN_FILE = "AWS_WEB_IDENTITY_TOKEN_F
|
|
|
23001
23001
|
roleSessionName
|
|
23002
23002
|
})(awsIdentityProperties);
|
|
23003
23003
|
if (webIdentityTokenFile === process.env[ENV_TOKEN_FILE]) {
|
|
23004
|
-
|
|
23004
|
+
import_client19.setCredentialFeature(credentials, "CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN", "h");
|
|
23005
23005
|
}
|
|
23006
23006
|
return credentials;
|
|
23007
23007
|
};
|
|
23008
23008
|
var init_fromTokenFile = __esm(() => {
|
|
23009
|
-
|
|
23009
|
+
import_client19 = __toESM(require_client2(), 1);
|
|
23010
23010
|
import_config24 = __toESM(require_config(), 1);
|
|
23011
23011
|
});
|
|
23012
23012
|
|
|
@@ -23021,7 +23021,7 @@ var init_dist_es8 = __esm(() => {
|
|
|
23021
23021
|
});
|
|
23022
23022
|
|
|
23023
23023
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-ini@3.973.15/node_modules/@aws-sdk/credential-provider-ini/dist-es/resolveWebIdentityCredentials.js
|
|
23024
|
-
var
|
|
23024
|
+
var import_client20, isWebIdentityProfile = (arg) => Boolean(arg) && typeof arg === "object" && typeof arg.web_identity_token_file === "string" && typeof arg.role_arn === "string" && ["undefined", "string"].indexOf(typeof arg.role_session_name) > -1, resolveWebIdentityCredentials = async (profile, options, callerClientConfig) => {
|
|
23025
23025
|
const { fromTokenFile: fromTokenFile2 } = await Promise.resolve().then(() => (init_dist_es8(), exports_dist_es7));
|
|
23026
23026
|
const credentials = await fromTokenFile2({
|
|
23027
23027
|
webIdentityTokenFile: profile.web_identity_token_file,
|
|
@@ -23033,10 +23033,10 @@ var import_client18, isWebIdentityProfile = (arg) => Boolean(arg) && typeof arg
|
|
|
23033
23033
|
})({
|
|
23034
23034
|
callerClientConfig
|
|
23035
23035
|
});
|
|
23036
|
-
return
|
|
23036
|
+
return import_client20.setCredentialFeature(credentials, "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN", "q");
|
|
23037
23037
|
};
|
|
23038
23038
|
var init_resolveWebIdentityCredentials = __esm(() => {
|
|
23039
|
-
|
|
23039
|
+
import_client20 = __toESM(require_client2(), 1);
|
|
23040
23040
|
});
|
|
23041
23041
|
|
|
23042
23042
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-ini@3.973.15/node_modules/@aws-sdk/credential-provider-ini/dist-es/resolveProfileData.js
|
|
@@ -23097,15 +23097,23 @@ var init_dist_es9 = __esm(() => {
|
|
|
23097
23097
|
init_fromIni();
|
|
23098
23098
|
});
|
|
23099
23099
|
|
|
23100
|
-
//
|
|
23100
|
+
// ../events/dist/index.js
|
|
23101
23101
|
import { chmod, mkdir, readFile, rename, writeFile as writeFile2 } from "fs/promises";
|
|
23102
23102
|
import { Buffer as Buffer2 } from "buffer";
|
|
23103
|
+
import { existsSync as existsSync22 } from "fs";
|
|
23104
|
+
import { join as join22 } from "path";
|
|
23103
23105
|
import { existsSync as existsSync16 } from "fs";
|
|
23104
23106
|
import { homedir as homedir5 } from "os";
|
|
23105
|
-
import { join as join20 } from "path";
|
|
23107
|
+
import { join as join20, resolve as resolve3 } from "path";
|
|
23108
|
+
import { homedir as pathsResolverHomedir2 } from "os";
|
|
23109
|
+
import { join as pathsResolverJoin2 } from "path";
|
|
23106
23110
|
import { createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
23111
|
+
import { lookup as dnsLookup } from "dns/promises";
|
|
23112
|
+
import { isIP as isIP2 } from "net";
|
|
23107
23113
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
23108
23114
|
import { spawn } from "child_process";
|
|
23115
|
+
import { request as nodeHttpRequest } from "http";
|
|
23116
|
+
import { request as nodeHttpsRequest } from "https";
|
|
23109
23117
|
import { randomUUID as randomUUID22 } from "crypto";
|
|
23110
23118
|
function getPathValue(input, path) {
|
|
23111
23119
|
return path.split(".").reduce((value, part) => {
|
|
@@ -23202,8 +23210,90 @@ function channelMatchesEvent(channel, event) {
|
|
|
23202
23210
|
return true;
|
|
23203
23211
|
return channel.filters.some((filter) => eventMatchesFilter(event, filter));
|
|
23204
23212
|
}
|
|
23213
|
+
function pathsResolverAssertApp2(app) {
|
|
23214
|
+
if (typeof app !== "string" || app.length === 0) {
|
|
23215
|
+
throw new TypeError("paths: app must be a non-empty string");
|
|
23216
|
+
}
|
|
23217
|
+
if (!PATHS_RESOLVER_APP_SLUG_RE2.test(app)) {
|
|
23218
|
+
throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
|
|
23219
|
+
}
|
|
23220
|
+
}
|
|
23221
|
+
function pathsResolverAssertKind(kind) {
|
|
23222
|
+
if (!Object.keys(PATHS_RESOLVER_KIND_ENV).includes(kind)) {
|
|
23223
|
+
throw new TypeError(`paths: invalid path kind "${kind}" \u2014 expected one of ${Object.keys(PATHS_RESOLVER_KIND_ENV).join(", ")}`);
|
|
23224
|
+
}
|
|
23225
|
+
}
|
|
23226
|
+
function pathsResolverBaseDir(kind, options) {
|
|
23227
|
+
pathsResolverAssertKind(kind);
|
|
23228
|
+
const env = options.env ?? process.env;
|
|
23229
|
+
const override = env[PATHS_RESOLVER_KIND_ENV[kind]];
|
|
23230
|
+
if (typeof override === "string" && override.length > 0)
|
|
23231
|
+
return override;
|
|
23232
|
+
const home = options.home ?? pathsResolverHomedir2();
|
|
23233
|
+
const platform = options.platform ?? process.platform;
|
|
23234
|
+
if (platform === "darwin") {
|
|
23235
|
+
switch (kind) {
|
|
23236
|
+
case "config":
|
|
23237
|
+
case "data":
|
|
23238
|
+
return pathsResolverJoin2(home, "Library", "Application Support", "Hasna");
|
|
23239
|
+
case "cache":
|
|
23240
|
+
return pathsResolverJoin2(home, "Library", "Caches", "Hasna");
|
|
23241
|
+
case "state":
|
|
23242
|
+
return pathsResolverJoin2(home, "Library", "Logs", "Hasna");
|
|
23243
|
+
}
|
|
23244
|
+
}
|
|
23245
|
+
switch (kind) {
|
|
23246
|
+
case "config":
|
|
23247
|
+
return pathsResolverJoin2(home, ".config", "hasna");
|
|
23248
|
+
case "data":
|
|
23249
|
+
return pathsResolverJoin2(home, ".local", "share", "hasna");
|
|
23250
|
+
case "state":
|
|
23251
|
+
return pathsResolverJoin2(home, ".local", "state", "hasna");
|
|
23252
|
+
case "cache":
|
|
23253
|
+
return pathsResolverJoin2(home, ".cache", "hasna");
|
|
23254
|
+
}
|
|
23255
|
+
}
|
|
23256
|
+
function pathsResolverResolve(kind, options) {
|
|
23257
|
+
pathsResolverAssertApp2(options.app);
|
|
23258
|
+
const appSegment = options.internal === true ? pathsResolverJoin2("internal", options.app) : options.app;
|
|
23259
|
+
return pathsResolverJoin2(pathsResolverBaseDir(kind, options), appSegment);
|
|
23260
|
+
}
|
|
23261
|
+
function dataDir2(options) {
|
|
23262
|
+
return pathsResolverResolve("data", options);
|
|
23263
|
+
}
|
|
23264
|
+
function effectiveHome2() {
|
|
23265
|
+
return process.env["HOME"] || process.env["USERPROFILE"] || homedir5();
|
|
23266
|
+
}
|
|
23267
|
+
function legacyHomeDir() {
|
|
23268
|
+
return join20(effectiveHome2(), ".hasna", "events");
|
|
23269
|
+
}
|
|
23270
|
+
function resolverHome() {
|
|
23271
|
+
return dataDir2({ app: "events", home: effectiveHome2() || undefined });
|
|
23272
|
+
}
|
|
23273
|
+
function adoptResolverHome(resolved, env = process.env) {
|
|
23274
|
+
const dataOverride = env.HASNA_DATA_HOME;
|
|
23275
|
+
if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
|
|
23276
|
+
return true;
|
|
23277
|
+
return existsSync16(join20(resolved, EVENTS_STORE_SENTINEL_FILE));
|
|
23278
|
+
}
|
|
23279
|
+
function exactEventsHome() {
|
|
23280
|
+
const dir = process.env[HASNA_EVENTS_DIR_ENV];
|
|
23281
|
+
if (dir && dir.trim())
|
|
23282
|
+
return dir.trim();
|
|
23283
|
+
const home = process.env[HASNA_EVENTS_HOME_ENV];
|
|
23284
|
+
if (home && home.trim())
|
|
23285
|
+
return home.trim();
|
|
23286
|
+
return;
|
|
23287
|
+
}
|
|
23288
|
+
function getEventsHome() {
|
|
23289
|
+
const exact = exactEventsHome();
|
|
23290
|
+
if (exact)
|
|
23291
|
+
return resolve3(exact);
|
|
23292
|
+
const resolved = resolverHome();
|
|
23293
|
+
return adoptResolverHome(resolved) ? resolve3(resolved) : resolve3(legacyHomeDir());
|
|
23294
|
+
}
|
|
23205
23295
|
function getEventsDataDir(override) {
|
|
23206
|
-
return override ||
|
|
23296
|
+
return override || getEventsHome();
|
|
23207
23297
|
}
|
|
23208
23298
|
|
|
23209
23299
|
class JsonEventsStore {
|
|
@@ -23212,12 +23302,12 @@ class JsonEventsStore {
|
|
|
23212
23302
|
channelsPath;
|
|
23213
23303
|
eventsPath;
|
|
23214
23304
|
deliveriesPath;
|
|
23215
|
-
constructor(
|
|
23216
|
-
this.dataDir =
|
|
23217
|
-
this.runtime = localJsonRuntime(
|
|
23218
|
-
this.channelsPath =
|
|
23219
|
-
this.eventsPath =
|
|
23220
|
-
this.deliveriesPath =
|
|
23305
|
+
constructor(dataDir22 = getEventsDataDir()) {
|
|
23306
|
+
this.dataDir = dataDir22;
|
|
23307
|
+
this.runtime = localJsonRuntime(dataDir22);
|
|
23308
|
+
this.channelsPath = join22(dataDir22, "channels.json");
|
|
23309
|
+
this.eventsPath = join22(dataDir22, "events.json");
|
|
23310
|
+
this.deliveriesPath = join22(dataDir22, "deliveries.json");
|
|
23221
23311
|
}
|
|
23222
23312
|
async init() {
|
|
23223
23313
|
await mkdir(this.dataDir, { recursive: true, mode: 448 });
|
|
@@ -23334,7 +23424,7 @@ class JsonEventsStore {
|
|
|
23334
23424
|
};
|
|
23335
23425
|
}
|
|
23336
23426
|
async ensureArrayFile(path) {
|
|
23337
|
-
if (!
|
|
23427
|
+
if (!existsSync22(path)) {
|
|
23338
23428
|
await writeFile2(path, `[]
|
|
23339
23429
|
`, { encoding: "utf-8", mode: 384 });
|
|
23340
23430
|
}
|
|
@@ -23364,7 +23454,7 @@ class JsonEventsStore {
|
|
|
23364
23454
|
});
|
|
23365
23455
|
}
|
|
23366
23456
|
}
|
|
23367
|
-
function localJsonRuntime(
|
|
23457
|
+
function localJsonRuntime(dataDir22 = getEventsDataDir()) {
|
|
23368
23458
|
return {
|
|
23369
23459
|
mode: "local-files",
|
|
23370
23460
|
name: "json-events-store",
|
|
@@ -23377,7 +23467,7 @@ function localJsonRuntime(dataDir2 = getEventsDataDir()) {
|
|
|
23377
23467
|
durable: true,
|
|
23378
23468
|
idempotency: "best-effort-local",
|
|
23379
23469
|
replayCursors: true,
|
|
23380
|
-
description: `Local JSON files in ${
|
|
23470
|
+
description: `Local JSON files in ${dataDir22}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
|
|
23381
23471
|
};
|
|
23382
23472
|
}
|
|
23383
23473
|
function encodeLocalJsonEventCursor(offset, options = {}) {
|
|
@@ -23448,6 +23538,177 @@ function signPayload(secret, timestamp, body) {
|
|
|
23448
23538
|
const digest2 = createHmac3("sha256", secret).update(buildSignatureBase(timestamp, body)).digest("hex");
|
|
23449
23539
|
return `sha256=${digest2}`;
|
|
23450
23540
|
}
|
|
23541
|
+
function isPrivateAddress(address) {
|
|
23542
|
+
const normalized = stripZoneId(address);
|
|
23543
|
+
const version2 = isIP2(normalized);
|
|
23544
|
+
if (version2 === 4) {
|
|
23545
|
+
const integer = ipv4ToInt(normalized);
|
|
23546
|
+
if (integer === undefined)
|
|
23547
|
+
return true;
|
|
23548
|
+
return IPV4_PRIVATE_RANGES.some(([low, high]) => integer >= low && integer <= high);
|
|
23549
|
+
}
|
|
23550
|
+
if (version2 === 6) {
|
|
23551
|
+
const groups = ipv6Groups(normalized);
|
|
23552
|
+
if (!groups)
|
|
23553
|
+
return true;
|
|
23554
|
+
for (const prefix of IPV6_SPECIAL_PREFIXES) {
|
|
23555
|
+
if (!ipv6MatchesPrefix(groups, prefix.groups, prefix.bits))
|
|
23556
|
+
continue;
|
|
23557
|
+
if (prefix.bits === 96 && groups[5] === 65535) {
|
|
23558
|
+
return isPrivateAddress(ipv4IntToString(groups[6] << 16 | groups[7]));
|
|
23559
|
+
}
|
|
23560
|
+
if (prefix.bits === 16 && groups[0] === 8194) {
|
|
23561
|
+
return isPrivateAddress(ipv4IntToString(groups[1] << 16 | groups[2]));
|
|
23562
|
+
}
|
|
23563
|
+
return true;
|
|
23564
|
+
}
|
|
23565
|
+
return false;
|
|
23566
|
+
}
|
|
23567
|
+
return true;
|
|
23568
|
+
}
|
|
23569
|
+
async function resolveWebhookTarget(url, policy = {}) {
|
|
23570
|
+
const hostname = normalizeHostname(url.hostname);
|
|
23571
|
+
const allowlist = (policy.allowPrivateHosts ?? []).map((entry) => normalizeHostname(entry.toLowerCase()));
|
|
23572
|
+
if (allowlist.includes(hostname)) {
|
|
23573
|
+
const version22 = isIP2(hostname);
|
|
23574
|
+
if (version22 === 4 || version22 === 6) {
|
|
23575
|
+
return { hostname, addresses: [hostname] };
|
|
23576
|
+
}
|
|
23577
|
+
const lookup2 = policy.lookup ?? defaultTargetLookup;
|
|
23578
|
+
let resolved2;
|
|
23579
|
+
try {
|
|
23580
|
+
resolved2 = await lookup2(hostname);
|
|
23581
|
+
} catch {
|
|
23582
|
+
throw new Error(`Webhook target ${hostname} could not be resolved`);
|
|
23583
|
+
}
|
|
23584
|
+
if (!Array.isArray(resolved2) || resolved2.length === 0) {
|
|
23585
|
+
throw new Error(`Webhook target ${hostname} resolved to no addresses`);
|
|
23586
|
+
}
|
|
23587
|
+
const addresses = resolved2.map((entry) => normalizeHostname(entry.address));
|
|
23588
|
+
return { hostname, addresses };
|
|
23589
|
+
}
|
|
23590
|
+
const version2 = isIP2(hostname);
|
|
23591
|
+
if (version2 === 4 || version2 === 6) {
|
|
23592
|
+
if (isPrivateAddress(hostname)) {
|
|
23593
|
+
throw new Error(`Webhook target ${hostname} is a private or special-use address`);
|
|
23594
|
+
}
|
|
23595
|
+
return { hostname, addresses: [hostname] };
|
|
23596
|
+
}
|
|
23597
|
+
const lookup = policy.lookup ?? defaultTargetLookup;
|
|
23598
|
+
let resolved;
|
|
23599
|
+
try {
|
|
23600
|
+
resolved = await lookup(hostname);
|
|
23601
|
+
} catch {
|
|
23602
|
+
throw new Error(`Webhook target ${hostname} could not be resolved`);
|
|
23603
|
+
}
|
|
23604
|
+
if (!Array.isArray(resolved) || resolved.length === 0) {
|
|
23605
|
+
throw new Error(`Webhook target ${hostname} resolved to no addresses`);
|
|
23606
|
+
}
|
|
23607
|
+
const allowed = [];
|
|
23608
|
+
for (const entry of resolved) {
|
|
23609
|
+
const address = normalizeHostname(entry.address);
|
|
23610
|
+
if (isPrivateAddress(address)) {
|
|
23611
|
+
if (allowlist.includes(address)) {
|
|
23612
|
+
allowed.push(address);
|
|
23613
|
+
continue;
|
|
23614
|
+
}
|
|
23615
|
+
throw new Error(`Webhook target ${hostname} resolves to private or special-use address ${address}`);
|
|
23616
|
+
}
|
|
23617
|
+
allowed.push(address);
|
|
23618
|
+
}
|
|
23619
|
+
if (allowed.length === 0) {
|
|
23620
|
+
throw new Error(`Webhook target ${hostname} resolved to no public addresses`);
|
|
23621
|
+
}
|
|
23622
|
+
return { hostname, addresses: allowed };
|
|
23623
|
+
}
|
|
23624
|
+
function normalizeMaxRedirects(value) {
|
|
23625
|
+
if (value === undefined)
|
|
23626
|
+
return DEFAULT_MAX_REDIRECTS;
|
|
23627
|
+
if (!Number.isInteger(value) || value < 0)
|
|
23628
|
+
throw new Error("webhookTargetPolicy.maxRedirects must be a non-negative integer");
|
|
23629
|
+
return value;
|
|
23630
|
+
}
|
|
23631
|
+
function normalizeHostname(hostname) {
|
|
23632
|
+
const lower = hostname.toLowerCase();
|
|
23633
|
+
if (lower.startsWith("[") && lower.endsWith("]"))
|
|
23634
|
+
return lower.slice(1, -1);
|
|
23635
|
+
return lower;
|
|
23636
|
+
}
|
|
23637
|
+
function stripZoneId(address) {
|
|
23638
|
+
const percent = address.indexOf("%");
|
|
23639
|
+
return percent === -1 ? address : address.slice(0, percent);
|
|
23640
|
+
}
|
|
23641
|
+
function ipv4ToInt(address) {
|
|
23642
|
+
const parts = address.split(".");
|
|
23643
|
+
if (parts.length !== 4)
|
|
23644
|
+
return;
|
|
23645
|
+
let value = 0;
|
|
23646
|
+
for (const part of parts) {
|
|
23647
|
+
if (!/^\d{1,3}$/.test(part))
|
|
23648
|
+
return;
|
|
23649
|
+
const octet = Number(part);
|
|
23650
|
+
if (octet > 255)
|
|
23651
|
+
return;
|
|
23652
|
+
value = value << 8 | octet;
|
|
23653
|
+
}
|
|
23654
|
+
return value >>> 0;
|
|
23655
|
+
}
|
|
23656
|
+
function ipv4IntToString(integer) {
|
|
23657
|
+
return [
|
|
23658
|
+
integer >>> 24 & 255,
|
|
23659
|
+
integer >>> 16 & 255,
|
|
23660
|
+
integer >>> 8 & 255,
|
|
23661
|
+
integer & 255
|
|
23662
|
+
].join(".");
|
|
23663
|
+
}
|
|
23664
|
+
function ipv6Groups(address) {
|
|
23665
|
+
const raw = stripZoneId(address);
|
|
23666
|
+
const doubleColon = raw.indexOf("::");
|
|
23667
|
+
const headText = doubleColon === -1 ? raw : raw.slice(0, doubleColon);
|
|
23668
|
+
const tailText = doubleColon === -1 ? "" : raw.slice(doubleColon + 2);
|
|
23669
|
+
const parseGroups = (text) => {
|
|
23670
|
+
if (text === "")
|
|
23671
|
+
return [];
|
|
23672
|
+
const out = [];
|
|
23673
|
+
for (const part of text.split(":")) {
|
|
23674
|
+
if (part.includes(".")) {
|
|
23675
|
+
const v4 = ipv4ToInt(part);
|
|
23676
|
+
if (v4 === undefined)
|
|
23677
|
+
return;
|
|
23678
|
+
out.push(v4 >>> 16 & 65535, v4 & 65535);
|
|
23679
|
+
} else {
|
|
23680
|
+
if (!/^[0-9a-fA-F]{1,4}$/.test(part))
|
|
23681
|
+
return;
|
|
23682
|
+
out.push(parseInt(part, 16));
|
|
23683
|
+
}
|
|
23684
|
+
}
|
|
23685
|
+
return out;
|
|
23686
|
+
};
|
|
23687
|
+
const head = parseGroups(headText);
|
|
23688
|
+
if (!head)
|
|
23689
|
+
return;
|
|
23690
|
+
const tail = parseGroups(tailText);
|
|
23691
|
+
if (!tail)
|
|
23692
|
+
return;
|
|
23693
|
+
const total = head.length + tail.length;
|
|
23694
|
+
if (doubleColon === -1) {
|
|
23695
|
+
return total === 8 ? head : undefined;
|
|
23696
|
+
}
|
|
23697
|
+
if (total >= 8)
|
|
23698
|
+
return;
|
|
23699
|
+
return [...head, ...new Array(8 - total).fill(0), ...tail];
|
|
23700
|
+
}
|
|
23701
|
+
function ipv6MatchesPrefix(groups, prefixGroups, prefixBits) {
|
|
23702
|
+
let remaining = prefixBits;
|
|
23703
|
+
for (let index = 0;index < prefixGroups.length && remaining > 0; index += 1) {
|
|
23704
|
+
const take = Math.min(16, remaining);
|
|
23705
|
+
const mask = 65535 << 16 - take & 65535;
|
|
23706
|
+
if ((groups[index] & mask) !== (prefixGroups[index] & mask))
|
|
23707
|
+
return false;
|
|
23708
|
+
remaining -= take;
|
|
23709
|
+
}
|
|
23710
|
+
return true;
|
|
23711
|
+
}
|
|
23451
23712
|
function now() {
|
|
23452
23713
|
return new Date().toISOString();
|
|
23453
23714
|
}
|
|
@@ -23478,9 +23739,18 @@ function buildWebhookRequest(event, channel, options = {}) {
|
|
|
23478
23739
|
}
|
|
23479
23740
|
return { body, headers };
|
|
23480
23741
|
}
|
|
23742
|
+
function normalizeWebhookUrl(raw) {
|
|
23743
|
+
const url = new URL(raw);
|
|
23744
|
+
if (url.username !== "" || url.password !== "") {
|
|
23745
|
+
url.username = "";
|
|
23746
|
+
url.password = "";
|
|
23747
|
+
}
|
|
23748
|
+
return url.toString();
|
|
23749
|
+
}
|
|
23481
23750
|
async function dispatchWebhook(event, channel, options = {}) {
|
|
23482
23751
|
if (!channel.webhook)
|
|
23483
23752
|
throw new Error(`Channel ${channel.id} has no webhook config`);
|
|
23753
|
+
const webhookUrl = normalizeWebhookUrl(channel.webhook.url);
|
|
23484
23754
|
const startedAt = now();
|
|
23485
23755
|
let secret = channel.webhook.secret;
|
|
23486
23756
|
if (channel.webhook.secretRef) {
|
|
@@ -23497,10 +23767,14 @@ async function dispatchWebhook(event, channel, options = {}) {
|
|
|
23497
23767
|
}
|
|
23498
23768
|
const timestamp = (options.now?.() ?? new Date).toISOString();
|
|
23499
23769
|
const { body, headers } = buildWebhookRequest(event, channel, { secret, timestamp });
|
|
23770
|
+
const validateTargets = options.webhookTargetPolicy !== undefined || options.fetchImpl === undefined;
|
|
23771
|
+
if (validateTargets) {
|
|
23772
|
+
return dispatchValidatedWebhook(event, channel, { body, headers, startedAt, options });
|
|
23773
|
+
}
|
|
23500
23774
|
const controller = new AbortController;
|
|
23501
23775
|
const timeout = setTimeout(() => controller.abort(), channel.webhook.timeoutMs ?? 15000);
|
|
23502
23776
|
try {
|
|
23503
|
-
const response = await (options.fetchImpl ?? fetch)(
|
|
23777
|
+
const response = await (options.fetchImpl ?? fetch)(webhookUrl, {
|
|
23504
23778
|
method: "POST",
|
|
23505
23779
|
headers,
|
|
23506
23780
|
body,
|
|
@@ -23528,6 +23802,130 @@ async function dispatchWebhook(event, channel, options = {}) {
|
|
|
23528
23802
|
clearTimeout(timeout);
|
|
23529
23803
|
}
|
|
23530
23804
|
}
|
|
23805
|
+
function isRedirectStatus(status) {
|
|
23806
|
+
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
23807
|
+
}
|
|
23808
|
+
function redirectKeepsBody(status) {
|
|
23809
|
+
return status === 307 || status === 308;
|
|
23810
|
+
}
|
|
23811
|
+
async function pinnedNativeRequest(target, addresses, method, headers, body, signal, tls) {
|
|
23812
|
+
const isHttps = target.protocol === "https:";
|
|
23813
|
+
if (!isHttps && target.protocol !== "http:") {
|
|
23814
|
+
throw new Error(`Webhook target uses unsupported protocol ${target.protocol}`);
|
|
23815
|
+
}
|
|
23816
|
+
const defaultPort = isHttps ? 443 : 80;
|
|
23817
|
+
const port = target.port ? Number(target.port) : defaultPort;
|
|
23818
|
+
const requestOptions = {
|
|
23819
|
+
hostname: target.hostname,
|
|
23820
|
+
port,
|
|
23821
|
+
path: `${target.pathname}${target.search}`,
|
|
23822
|
+
method,
|
|
23823
|
+
headers,
|
|
23824
|
+
...tls?.ca ? { ca: tls.ca } : {},
|
|
23825
|
+
lookup: (hostname, _options, callback) => {
|
|
23826
|
+
const entries = addresses.map((address) => ({
|
|
23827
|
+
address,
|
|
23828
|
+
family: address.includes(":") ? 6 : 4
|
|
23829
|
+
}));
|
|
23830
|
+
callback(null, entries);
|
|
23831
|
+
}
|
|
23832
|
+
};
|
|
23833
|
+
return new Promise((resolve22, reject) => {
|
|
23834
|
+
const request = isHttps ? nodeHttpsRequest(requestOptions, onResponse) : nodeHttpRequest(requestOptions, onResponse);
|
|
23835
|
+
const onAbort = () => {
|
|
23836
|
+
const error = new Error("The operation was aborted.");
|
|
23837
|
+
error.name = "AbortError";
|
|
23838
|
+
request.destroy(error);
|
|
23839
|
+
};
|
|
23840
|
+
if (signal.aborted)
|
|
23841
|
+
onAbort();
|
|
23842
|
+
else
|
|
23843
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
23844
|
+
request.on("error", reject);
|
|
23845
|
+
if (body !== undefined)
|
|
23846
|
+
request.write(body);
|
|
23847
|
+
request.end();
|
|
23848
|
+
function onResponse(response) {
|
|
23849
|
+
const chunks = [];
|
|
23850
|
+
response.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
23851
|
+
response.on("error", reject);
|
|
23852
|
+
response.on("end", () => {
|
|
23853
|
+
const headersRecord = {};
|
|
23854
|
+
for (const [name, value] of Object.entries(response.headers)) {
|
|
23855
|
+
if (typeof value === "string")
|
|
23856
|
+
headersRecord[name] = value;
|
|
23857
|
+
else if (Array.isArray(value))
|
|
23858
|
+
headersRecord[name] = value.join(", ");
|
|
23859
|
+
}
|
|
23860
|
+
resolve22(new Response(Buffer.concat(chunks), { status: response.statusCode ?? 200, headers: headersRecord }));
|
|
23861
|
+
});
|
|
23862
|
+
}
|
|
23863
|
+
});
|
|
23864
|
+
}
|
|
23865
|
+
async function dispatchValidatedWebhook(event, channel, input) {
|
|
23866
|
+
const { body, headers, startedAt, options } = input;
|
|
23867
|
+
const webhook = channel.webhook;
|
|
23868
|
+
if (!webhook)
|
|
23869
|
+
throw new Error(`Channel ${channel.id} has no webhook config`);
|
|
23870
|
+
const policy = options.webhookTargetPolicy ?? {};
|
|
23871
|
+
const maxRedirects = normalizeMaxRedirects(policy.maxRedirects);
|
|
23872
|
+
const controller = new AbortController;
|
|
23873
|
+
const timeout = setTimeout(() => controller.abort(), webhook.timeoutMs ?? 15000);
|
|
23874
|
+
try {
|
|
23875
|
+
let target = new URL(normalizeWebhookUrl(webhook.url));
|
|
23876
|
+
let requestHeaders = headers;
|
|
23877
|
+
let method = "POST";
|
|
23878
|
+
let requestBody = body;
|
|
23879
|
+
let redirectsFollowed = 0;
|
|
23880
|
+
for (;; ) {
|
|
23881
|
+
const resolved = await resolveWebhookTarget(target, policy).catch((error) => {
|
|
23882
|
+
throw new Error(`Webhook target rejected by SSRF guard: ${error.message}`);
|
|
23883
|
+
});
|
|
23884
|
+
const response = options.fetchImpl ? await options.fetchImpl(target, {
|
|
23885
|
+
method,
|
|
23886
|
+
headers: requestHeaders,
|
|
23887
|
+
body: requestBody,
|
|
23888
|
+
signal: controller.signal,
|
|
23889
|
+
redirect: "manual"
|
|
23890
|
+
}) : await pinnedNativeRequest(target, resolved.addresses, method, requestHeaders, requestBody, controller.signal, options.tls);
|
|
23891
|
+
const location = response.headers.get("location");
|
|
23892
|
+
if (isRedirectStatus(response.status) && location) {
|
|
23893
|
+
if (redirectsFollowed >= maxRedirects) {
|
|
23894
|
+
return failedAttempt(startedAt, `Webhook target exceeded ${maxRedirects} redirects`);
|
|
23895
|
+
}
|
|
23896
|
+
redirectsFollowed += 1;
|
|
23897
|
+
const next = new URL(location, target);
|
|
23898
|
+
target = next;
|
|
23899
|
+
if (!redirectKeepsBody(response.status)) {
|
|
23900
|
+
method = "GET";
|
|
23901
|
+
requestBody = undefined;
|
|
23902
|
+
requestHeaders = Object.fromEntries(Object.entries(requestHeaders).filter(([name]) => name.toLowerCase() !== "content-type" && name.toLowerCase() !== "content-length"));
|
|
23903
|
+
}
|
|
23904
|
+
continue;
|
|
23905
|
+
}
|
|
23906
|
+
const responseBody = truncate(await response.text());
|
|
23907
|
+
return {
|
|
23908
|
+
attempt: 1,
|
|
23909
|
+
status: response.ok ? "success" : "failed",
|
|
23910
|
+
startedAt,
|
|
23911
|
+
completedAt: now(),
|
|
23912
|
+
responseStatus: response.status,
|
|
23913
|
+
responseBody,
|
|
23914
|
+
error: response.ok ? undefined : `Webhook returned HTTP ${response.status}`
|
|
23915
|
+
};
|
|
23916
|
+
}
|
|
23917
|
+
} catch (error) {
|
|
23918
|
+
return {
|
|
23919
|
+
attempt: 1,
|
|
23920
|
+
status: "failed",
|
|
23921
|
+
startedAt,
|
|
23922
|
+
completedAt: now(),
|
|
23923
|
+
error: error instanceof Error ? error.message : String(error)
|
|
23924
|
+
};
|
|
23925
|
+
} finally {
|
|
23926
|
+
clearTimeout(timeout);
|
|
23927
|
+
}
|
|
23928
|
+
}
|
|
23531
23929
|
function failedAttempt(startedAt, error) {
|
|
23532
23930
|
return {
|
|
23533
23931
|
attempt: 1,
|
|
@@ -23556,7 +23954,7 @@ async function dispatchCommand(event, channel) {
|
|
|
23556
23954
|
HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
|
|
23557
23955
|
HASNA_EVENT_JSON: eventJson
|
|
23558
23956
|
};
|
|
23559
|
-
return new Promise((
|
|
23957
|
+
return new Promise((resolve22) => {
|
|
23560
23958
|
const child = spawn(channel.command.command, channel.command.args ?? [], {
|
|
23561
23959
|
cwd: channel.command.cwd,
|
|
23562
23960
|
env,
|
|
@@ -23574,7 +23972,7 @@ async function dispatchCommand(event, channel) {
|
|
|
23574
23972
|
});
|
|
23575
23973
|
child.on("error", (error) => {
|
|
23576
23974
|
clearTimeout(timeout);
|
|
23577
|
-
|
|
23975
|
+
resolve22({
|
|
23578
23976
|
attempt: 1,
|
|
23579
23977
|
status: "failed",
|
|
23580
23978
|
startedAt,
|
|
@@ -23587,7 +23985,7 @@ async function dispatchCommand(event, channel) {
|
|
|
23587
23985
|
child.on("close", (code, signal) => {
|
|
23588
23986
|
clearTimeout(timeout);
|
|
23589
23987
|
const success = code === 0;
|
|
23590
|
-
|
|
23988
|
+
resolve22({
|
|
23591
23989
|
attempt: 1,
|
|
23592
23990
|
status: success ? "success" : "failed",
|
|
23593
23991
|
startedAt,
|
|
@@ -23723,7 +24121,9 @@ class EventsClient {
|
|
|
23723
24121
|
this.transportOptions = {
|
|
23724
24122
|
fetchImpl: options.fetchImpl,
|
|
23725
24123
|
secretResolver: options.secretResolver,
|
|
23726
|
-
now: options.now
|
|
24124
|
+
now: options.now,
|
|
24125
|
+
tls: options.tls,
|
|
24126
|
+
webhookTargetPolicy: options.webhookTargetPolicy
|
|
23727
24127
|
};
|
|
23728
24128
|
this.catalog = options.catalog ?? defaultEventTypeCatalog;
|
|
23729
24129
|
this.validateCatalogTypes = options.validateCatalogTypes ?? false;
|
|
@@ -23928,9 +24328,51 @@ function normalizeRetryPolicy(policy) {
|
|
|
23928
24328
|
multiplier: Math.max(1, policy?.multiplier ?? 2)
|
|
23929
24329
|
};
|
|
23930
24330
|
}
|
|
23931
|
-
var HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR", HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME", LOCAL_JSON_EVENT_CURSOR_PREFIX = "local-json-v1:", DEFAULT_EVENT_PAGE_LIMIT = 100, MAX_EVENT_PAGE_LIMIT = 1000, DEFAULT_SIGNATURE_TOLERANCE_MS,
|
|
24331
|
+
var PATHS_RESOLVER_KIND_ENV, PATHS_RESOLVER_APP_SLUG_RE2, 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) => {
|
|
24332
|
+
return dnsLookup(hostname, { all: true, verbatim: false });
|
|
24333
|
+
}, EventValidationError, defaultEventTypeCatalog, APP_EVENT_V1_MAX_DATA_BYTES;
|
|
23932
24334
|
var init_dist = __esm(() => {
|
|
24335
|
+
PATHS_RESOLVER_KIND_ENV = {
|
|
24336
|
+
config: "HASNA_CONFIG_HOME",
|
|
24337
|
+
data: "HASNA_DATA_HOME",
|
|
24338
|
+
state: "HASNA_STATE_HOME",
|
|
24339
|
+
cache: "HASNA_CACHE_HOME"
|
|
24340
|
+
};
|
|
24341
|
+
PATHS_RESOLVER_APP_SLUG_RE2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
23933
24342
|
DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
|
|
24343
|
+
IPV4_PRIVATE_RANGES = [
|
|
24344
|
+
[0, 16777215],
|
|
24345
|
+
[167772160, 184549375],
|
|
24346
|
+
[1681915904, 1686110207],
|
|
24347
|
+
[2130706432, 2147483647],
|
|
24348
|
+
[2851995648, 2852061183],
|
|
24349
|
+
[2886729728, 2887778303],
|
|
24350
|
+
[3221225472, 3221225727],
|
|
24351
|
+
[3221225984, 3221226239],
|
|
24352
|
+
[3227017984, 3227018239],
|
|
24353
|
+
[3232235520, 3232301055],
|
|
24354
|
+
[3323068416, 3323199487],
|
|
24355
|
+
[3325256704, 3325256959],
|
|
24356
|
+
[3405803776, 3405804031],
|
|
24357
|
+
[3758096384, 4294967295]
|
|
24358
|
+
];
|
|
24359
|
+
IPV6_SPECIAL_PREFIXES = [
|
|
24360
|
+
{ groups: [0, 0, 0, 0, 0, 0, 0, 0], bits: 128 },
|
|
24361
|
+
{ groups: [0, 0, 0, 0, 0, 0, 0, 1], bits: 128 },
|
|
24362
|
+
{ groups: [0, 0, 0, 0, 0, 65535, 0, 0], bits: 96 },
|
|
24363
|
+
{ groups: [100, 65435, 0, 0, 0, 0, 0, 0], bits: 96 },
|
|
24364
|
+
{ groups: [256, 0, 0, 0, 0, 0, 0, 0], bits: 64 },
|
|
24365
|
+
{ groups: [8193, 0, 0, 0, 0, 0, 0, 0], bits: 32 },
|
|
24366
|
+
{ groups: [8193, 2, 0, 0, 0, 0, 0, 0], bits: 48 },
|
|
24367
|
+
{ groups: [8193, 16, 0, 0, 0, 0, 0, 0], bits: 28 },
|
|
24368
|
+
{ groups: [8193, 3512, 0, 0, 0, 0, 0, 0], bits: 32 },
|
|
24369
|
+
{ groups: [8194, 0, 0, 0, 0, 0, 0, 0], bits: 16 },
|
|
24370
|
+
{ groups: [16383, 0, 0, 0, 0, 0, 0, 0], bits: 20 },
|
|
24371
|
+
{ groups: [64512, 0, 0, 0, 0, 0, 0, 0], bits: 7 },
|
|
24372
|
+
{ groups: [65152, 0, 0, 0, 0, 0, 0, 0], bits: 10 },
|
|
24373
|
+
{ groups: [65216, 0, 0, 0, 0, 0, 0, 0], bits: 10 },
|
|
24374
|
+
{ groups: [65280, 0, 0, 0, 0, 0, 0, 0], bits: 8 }
|
|
24375
|
+
];
|
|
23934
24376
|
EventValidationError = class EventValidationError extends Error {
|
|
23935
24377
|
eventType;
|
|
23936
24378
|
issues;
|
|
@@ -24525,7 +24967,6 @@ async function completePointerCredential(name, pointerResolution, env = process.
|
|
|
24525
24967
|
});
|
|
24526
24968
|
}
|
|
24527
24969
|
var DEFAULT_FLEET_GATEWAY_ORIGIN = "https://api.hasna.com";
|
|
24528
|
-
var DEFAULT_AUTHORITY_SOURCE = "default";
|
|
24529
24970
|
function defaultFleetGatewayBaseUrl(name) {
|
|
24530
24971
|
return `${DEFAULT_FLEET_GATEWAY_ORIGIN}/${validateAppSlug(name)}`;
|
|
24531
24972
|
}
|
|
@@ -24644,110 +25085,124 @@ function toV1BaseUrl(apiUrl) {
|
|
|
24644
25085
|
url.pathname = `${path}/v1`;
|
|
24645
25086
|
return url.toString().replace(/\/+$/, "");
|
|
24646
25087
|
}
|
|
24647
|
-
|
|
24648
|
-
|
|
24649
|
-
|
|
24650
|
-
|
|
24651
|
-
|
|
24652
|
-
|
|
24653
|
-
|
|
24654
|
-
|
|
24655
|
-
|
|
25088
|
+
var IDEMPOTENT_METHODS = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
|
|
25089
|
+
var AUTHORITY_OVERRIDE_HEADERS = new Set([
|
|
25090
|
+
"host",
|
|
25091
|
+
":authority",
|
|
25092
|
+
"forwarded",
|
|
25093
|
+
"x-forwarded-host",
|
|
25094
|
+
"x-original-host"
|
|
25095
|
+
]);
|
|
25096
|
+
|
|
25097
|
+
// src/lib/instance-credentials.ts
|
|
25098
|
+
import { closeSync as closeSync2, constants, fstatSync as fstatSync2, lstatSync, openSync as openSync2, readSync } from "fs";
|
|
25099
|
+
var SKILLS_BOUND_API_URL = "HASNA_SKILLS_BOUND_API_URL";
|
|
25100
|
+
function selectedSkillsProfile(env, explicit) {
|
|
25101
|
+
const selected = explicit ?? env.HASNA_PROFILE;
|
|
25102
|
+
if (selected === undefined)
|
|
25103
|
+
return null;
|
|
25104
|
+
const profile = selected.trim();
|
|
25105
|
+
if (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(profile))
|
|
25106
|
+
throw new Error("Invalid Skills credential profile");
|
|
25107
|
+
return profile;
|
|
24656
25108
|
}
|
|
24657
|
-
function
|
|
24658
|
-
env
|
|
24659
|
-
|
|
24660
|
-
|
|
24661
|
-
|
|
24662
|
-
|
|
24663
|
-
|
|
24664
|
-
|
|
24665
|
-
|
|
24666
|
-
|
|
24667
|
-
throw new ClientTransportConfigurationError(name, `${controlledUrl.key} contains ASCII control characters.`, [controlledUrl.key]);
|
|
24668
|
-
}
|
|
24669
|
-
const usableUrlEntries = definedUrlEntries.map((entry) => ({ key: entry.key, value: entry.raw.trim() }));
|
|
24670
|
-
if (usableUrlEntries.length > 1 && new Set(usableUrlEntries.map((entry) => entry.value)).size > 1) {
|
|
24671
|
-
throw new ClientTransportConfigurationError(name, `${usableUrlEntries.map((entry) => entry.key).join(" and ")} disagree; client authority aliases must be identical or only one may be set.`, usableUrlEntries.map((entry) => entry.key));
|
|
24672
|
-
}
|
|
24673
|
-
const envUrlHit = usableUrlEntries[0] ?? null;
|
|
24674
|
-
const keychainUrlHit = keychainConfigValue(name, env, options.credentials?.keychain);
|
|
24675
|
-
const diskConfigUrlHit = appConfigDiskValue(name, env, keys.apiUrlKeys);
|
|
24676
|
-
if (diskConfigUrlHit?.unusable) {
|
|
24677
|
-
throw new ClientTransportConfigurationError(name, `${diskConfigUrlHit.key} in ${diskConfigUrlHit.path} is declared but blank or malformed; public clients require a valid HTTPS service authority.`, [diskConfigUrlHit.path]);
|
|
24678
|
-
}
|
|
24679
|
-
const urlCandidates = [
|
|
24680
|
-
...envUrlHit ? [envUrlHit] : [],
|
|
24681
|
-
...keychainUrlHit ? [{ key: keychainUrlHit.source, value: keychainUrlHit.value }] : [],
|
|
24682
|
-
...diskConfigUrlHit ? [{ key: diskConfigUrlHit.path, value: diskConfigUrlHit.value.trim() }] : []
|
|
24683
|
-
];
|
|
24684
|
-
const configuredUrl = urlCandidates[0] ?? null;
|
|
24685
|
-
const divergentUrls = urlCandidates.filter((candidate) => candidate.value !== configuredUrl?.value);
|
|
24686
|
-
if (configuredUrl && divergentUrls.length > 0) {
|
|
24687
|
-
throw new ClientTransportConfigurationError(name, `${configuredUrl.key} and ${divergentUrls.map((candidate) => candidate.key).join(" and ")} select different service authorities; refusing to send a credential written for one authority to the other.`, urlCandidates.map((candidate) => candidate.key));
|
|
24688
|
-
}
|
|
24689
|
-
const warnings = [];
|
|
24690
|
-
if (configuredUrl && !envUrlHit) {
|
|
24691
|
-
warnings.push(`No ${keys.apiUrlKeys[0]} in the environment; the server URL in ${configuredUrl.key} was used, so this client connects to the server. ` + `Keep that entry aligned with the intended service authority.`);
|
|
25109
|
+
function skillsProfileCredentialFiles(env, explicit) {
|
|
25110
|
+
return credentialDiskSourceList("skills", env, selectedSkillsProfile(env, explicit)).map((source) => source.path);
|
|
25111
|
+
}
|
|
25112
|
+
function fileIdentity(file) {
|
|
25113
|
+
try {
|
|
25114
|
+
return lstatSync(file);
|
|
25115
|
+
} catch (error) {
|
|
25116
|
+
if (["ENOENT", "ENOTDIR"].includes(error.code ?? ""))
|
|
25117
|
+
return null;
|
|
25118
|
+
throw new Error("Cannot inspect Skills instance configuration");
|
|
24692
25119
|
}
|
|
24693
|
-
|
|
24694
|
-
|
|
24695
|
-
|
|
24696
|
-
|
|
24697
|
-
|
|
24698
|
-
|
|
24699
|
-
|
|
24700
|
-
|
|
24701
|
-
|
|
24702
|
-
let urlHit;
|
|
24703
|
-
if (configuredUrl) {
|
|
24704
|
-
urlHit = configuredUrl;
|
|
24705
|
-
} else {
|
|
24706
|
-
try {
|
|
24707
|
-
urlHit = { key: DEFAULT_AUTHORITY_SOURCE, value: defaultFleetGatewayBaseUrl(name) };
|
|
24708
|
-
} catch (error) {
|
|
24709
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
24710
|
-
throw new ClientTransportConfigurationError(name, `No ${keys.apiUrlKeys[0]} is configured and the default fleet gateway authority cannot be composed for '${name}': ${message}`, [keys.apiUrlKeys[0]]);
|
|
25120
|
+
}
|
|
25121
|
+
function unchanged(before, after) {
|
|
25122
|
+
return before === null || after === null ? before === after : ["dev", "ino", "size", "mtimeMs", "ctimeMs", "mode", "uid"].every((key) => before[key] === after[key]);
|
|
25123
|
+
}
|
|
25124
|
+
function captureSkillsCredentialFiles(files) {
|
|
25125
|
+
const identities = files.map((file) => [file, fileIdentity(file)]);
|
|
25126
|
+
return () => {
|
|
25127
|
+
if (identities.some(([file, before]) => !unchanged(before, fileIdentity(file)))) {
|
|
25128
|
+
throw new Error("Skills instance configuration changed while resolving credentials; retry without sending a credential");
|
|
24711
25129
|
}
|
|
24712
|
-
}
|
|
24713
|
-
|
|
24714
|
-
|
|
25130
|
+
};
|
|
25131
|
+
}
|
|
25132
|
+
function readMetadataText(file) {
|
|
25133
|
+
let fd;
|
|
24715
25134
|
try {
|
|
24716
|
-
|
|
25135
|
+
fd = openSync2(file, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
24717
25136
|
} catch (error) {
|
|
24718
|
-
|
|
24719
|
-
|
|
25137
|
+
if (["ENOENT", "ENOTDIR"].includes(error.code ?? ""))
|
|
25138
|
+
return null;
|
|
25139
|
+
throw new Error("Cannot safely read Skills instance configuration");
|
|
25140
|
+
}
|
|
25141
|
+
try {
|
|
25142
|
+
const before = fstatSync2(fd);
|
|
25143
|
+
const uid = process.getuid?.() ?? process.geteuid?.();
|
|
25144
|
+
if (!before.isFile() || ![256, 384].includes(before.mode & 4095) || uid !== undefined && before.uid !== uid || before.size > 64 * 1024) {
|
|
25145
|
+
throw new Error("Unsafe Skills instance configuration; expected a bounded owner-only regular file");
|
|
25146
|
+
}
|
|
25147
|
+
const bytes = Buffer.alloc(64 * 1024 + 1);
|
|
25148
|
+
let length = 0;
|
|
25149
|
+
while (length < bytes.length) {
|
|
25150
|
+
const count = readSync(fd, bytes, length, bytes.length - length, null);
|
|
25151
|
+
if (!count)
|
|
25152
|
+
break;
|
|
25153
|
+
length += count;
|
|
25154
|
+
}
|
|
25155
|
+
if (length > 64 * 1024 || !unchanged(before, fstatSync2(fd)) || !unchanged(before, fileIdentity(file))) {
|
|
25156
|
+
throw new Error("Skills instance configuration changed while reading");
|
|
25157
|
+
}
|
|
25158
|
+
return bytes.subarray(0, length).toString("utf8");
|
|
25159
|
+
} finally {
|
|
25160
|
+
closeSync2(fd);
|
|
24720
25161
|
}
|
|
24721
|
-
return {
|
|
24722
|
-
resolution: {
|
|
24723
|
-
transport: "http",
|
|
24724
|
-
transportSource: urlHit.key,
|
|
24725
|
-
baseUrl,
|
|
24726
|
-
apiUrlSource,
|
|
24727
|
-
apiKeyPresent: true,
|
|
24728
|
-
apiKeySource: credential.source,
|
|
24729
|
-
apiKeyTier: credential.tier,
|
|
24730
|
-
misconfigured: false,
|
|
24731
|
-
warning: warnings.length > 0 ? warnings.join(" ") : null
|
|
24732
|
-
},
|
|
24733
|
-
credential
|
|
24734
|
-
};
|
|
24735
25162
|
}
|
|
24736
|
-
function
|
|
24737
|
-
|
|
25163
|
+
function readSkillsInstanceMetadata(file) {
|
|
25164
|
+
const text = readMetadataText(file);
|
|
25165
|
+
if (text === null)
|
|
25166
|
+
return {};
|
|
25167
|
+
const values = new Map;
|
|
25168
|
+
for (const line of text.split(/\r?\n/)) {
|
|
25169
|
+
const match = /^\s*(?:export\s+)?(HASNA_SKILLS_API_URL|SKILLS_API_URL|HASNA_SKILLS_BOUND_API_URL)\s*=\s*(.*)$/.exec(line);
|
|
25170
|
+
if (!match)
|
|
25171
|
+
continue;
|
|
25172
|
+
let value = match[2].trim();
|
|
25173
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))
|
|
25174
|
+
value = value.slice(1, -1);
|
|
25175
|
+
if (!value || /[\x00-\x20\x7f]/.test(value) || values.has(match[1]))
|
|
25176
|
+
throw new Error("Invalid Skills instance configuration");
|
|
25177
|
+
values.set(match[1], value);
|
|
25178
|
+
}
|
|
25179
|
+
const urls = [values.get("HASNA_SKILLS_API_URL"), values.get("SKILLS_API_URL")].filter(Boolean);
|
|
25180
|
+
if (new Set(urls).size > 1)
|
|
25181
|
+
throw new Error("Skills API URL aliases disagree");
|
|
25182
|
+
return { apiUrl: urls[0], binding: values.get(SKILLS_BOUND_API_URL) };
|
|
24738
25183
|
}
|
|
24739
|
-
|
|
24740
|
-
|
|
24741
|
-
|
|
25184
|
+
|
|
25185
|
+
// src/lib/local-opt-in.ts
|
|
25186
|
+
var SKILLS_LOCAL_OPT_IN_ENV_KEYS = ["HASNA_SKILLS_LOCAL", "SKILLS_LOCAL"];
|
|
25187
|
+
function isSkillsLocalOptIn(env = process.env) {
|
|
25188
|
+
return SKILLS_LOCAL_OPT_IN_ENV_KEYS.some((key) => (env[key] ?? "").trim() !== "");
|
|
25189
|
+
}
|
|
25190
|
+
function skillsAuthorityEnvKeys() {
|
|
25191
|
+
const keys = clientTransportEnvKeys("skills");
|
|
25192
|
+
return [
|
|
25193
|
+
...keys.apiUrlKeys,
|
|
25194
|
+
...keys.apiKeyKeys,
|
|
25195
|
+
credentialOverrideEnvKey("skills"),
|
|
25196
|
+
credentialPointerEnvKey("skills"),
|
|
25197
|
+
CREDENTIAL_PROFILE_ENV_KEY
|
|
25198
|
+
];
|
|
25199
|
+
}
|
|
25200
|
+
function hasSkillsEnvAuthorityIntent(env = process.env) {
|
|
25201
|
+
return skillsAuthorityEnvKeys().some((key) => (env[key] ?? "").trim() !== "");
|
|
25202
|
+
}
|
|
25203
|
+
function selectsSkillsLocalMode(env = process.env) {
|
|
25204
|
+
return !hasSkillsEnvAuthorityIntent(env) && isSkillsLocalOptIn(env);
|
|
24742
25205
|
}
|
|
24743
|
-
var IDEMPOTENT_METHODS = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
|
|
24744
|
-
var AUTHORITY_OVERRIDE_HEADERS = new Set([
|
|
24745
|
-
"host",
|
|
24746
|
-
":authority",
|
|
24747
|
-
"forwarded",
|
|
24748
|
-
"x-forwarded-host",
|
|
24749
|
-
"x-original-host"
|
|
24750
|
-
]);
|
|
24751
25206
|
|
|
24752
25207
|
// src/lib/fleet-credentials.ts
|
|
24753
25208
|
var SKILLS_APP = "skills";
|
|
@@ -24765,12 +25220,12 @@ class SkillsFleetCredentialError extends Error {
|
|
|
24765
25220
|
this.code = code;
|
|
24766
25221
|
}
|
|
24767
25222
|
}
|
|
24768
|
-
function isClientTransportConfigurationError(error) {
|
|
24769
|
-
return error instanceof ClientTransportConfigurationError || typeof error === "object" && error !== null && error.name === "ClientTransportConfigurationError";
|
|
24770
|
-
}
|
|
24771
25223
|
function isCredentialResolutionError(error) {
|
|
24772
25224
|
return error instanceof CredentialResolutionError || typeof error === "object" && error !== null && error.name === "CredentialResolutionError";
|
|
24773
25225
|
}
|
|
25226
|
+
function isSkillsFleetCredentialError(error) {
|
|
25227
|
+
return error instanceof SkillsFleetCredentialError || typeof error === "object" && error !== null && error.name === "SkillsFleetCredentialError";
|
|
25228
|
+
}
|
|
24774
25229
|
function asSkillsFleetCredentialError(error) {
|
|
24775
25230
|
if (!isCredentialResolutionError(error))
|
|
24776
25231
|
return null;
|
|
@@ -24778,6 +25233,9 @@ function asSkillsFleetCredentialError(error) {
|
|
|
24778
25233
|
}
|
|
24779
25234
|
function normalizeSkillsApiOrigin(apiUrl) {
|
|
24780
25235
|
const url = new URL(apiUrl);
|
|
25236
|
+
if (url.username || url.password || url.search || url.hash || url.protocol !== "https:" && !(url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname))) {
|
|
25237
|
+
throw new SkillsFleetCredentialError("A Skills API URL must use HTTPS (or loopback HTTP), without credentials, query or fragment", "INVALID_API_URL");
|
|
25238
|
+
}
|
|
24781
25239
|
const pathname = url.pathname.replace(/\/+$/, "");
|
|
24782
25240
|
if (pathname === "/api" || pathname === "/api/v1") {
|
|
24783
25241
|
url.pathname = "/";
|
|
@@ -24788,11 +25246,24 @@ function normalizeSkillsApiOrigin(apiUrl) {
|
|
|
24788
25246
|
}
|
|
24789
25247
|
return url.toString().replace(/\/+$/, "");
|
|
24790
25248
|
}
|
|
24791
|
-
function configuredSkillsApiUrl(env = process.env, keychain) {
|
|
24792
|
-
|
|
24793
|
-
|
|
24794
|
-
if (value)
|
|
24795
|
-
|
|
25249
|
+
function configuredSkillsApiUrl(env = process.env, keychain, profile) {
|
|
25250
|
+
const declared = SKILLS_API_URL_ENV_KEYS.filter((key) => env[key] !== undefined).map((key) => ({ key, value: env[key] }));
|
|
25251
|
+
for (const entry of declared) {
|
|
25252
|
+
if (!entry.value.trim() || /[\x00-\x1f\x7f]/.test(entry.value))
|
|
25253
|
+
throw new SkillsFleetCredentialError(`${entry.key} is blank or contains control characters`, "INVALID_API_URL");
|
|
25254
|
+
}
|
|
25255
|
+
const normalized = declared.map((entry) => ({ value: normalizeSkillsApiOrigin(entry.value), source: entry.key }));
|
|
25256
|
+
if (new Set(normalized.map((entry) => entry.value)).size > 1)
|
|
25257
|
+
throw new SkillsFleetCredentialError("Skills API URL aliases disagree", "INVALID_API_URL");
|
|
25258
|
+
if (normalized[0])
|
|
25259
|
+
return normalized[0];
|
|
25260
|
+
if (selectedSkillsProfile(env, profile)) {
|
|
25261
|
+
for (const file of skillsProfileCredentialFiles(env, profile)) {
|
|
25262
|
+
const metadata = readSkillsInstanceMetadata(file);
|
|
25263
|
+
if (metadata.apiUrl || metadata.binding)
|
|
25264
|
+
return { value: metadata.apiUrl ?? metadata.binding, source: file };
|
|
25265
|
+
}
|
|
25266
|
+
return { value: defaultFleetGatewayBaseUrl(SKILLS_APP), source: "default" };
|
|
24796
25267
|
}
|
|
24797
25268
|
const fromKeychain = keychainConfigValue(SKILLS_APP, env, keychain);
|
|
24798
25269
|
if (fromKeychain)
|
|
@@ -24806,7 +25277,7 @@ function configuredSkillsApiUrl(env = process.env, keychain) {
|
|
|
24806
25277
|
return null;
|
|
24807
25278
|
}
|
|
24808
25279
|
function skillsCredentialFiles(env = process.env) {
|
|
24809
|
-
return
|
|
25280
|
+
return skillsProfileCredentialFiles(env);
|
|
24810
25281
|
}
|
|
24811
25282
|
function skillsCredentialFilePath(env = process.env) {
|
|
24812
25283
|
const paths = skillsCredentialFiles(env);
|
|
@@ -24821,11 +25292,15 @@ function noticeLocalSkillsMode(write = (line) => console.error(line)) {
|
|
|
24821
25292
|
if (localNoticePrinted)
|
|
24822
25293
|
return;
|
|
24823
25294
|
localNoticePrinted = true;
|
|
24824
|
-
write(`skills: local mode
|
|
25295
|
+
write(`skills: local mode (${SKILLS_LOCAL_OPT_IN_ENV_KEYS[0]}=1) \u2014 running on this machine against the bundled corpus.`);
|
|
24825
25296
|
}
|
|
24826
25297
|
function resolveSkillsFleet(env = process.env, options = {}) {
|
|
24827
25298
|
try {
|
|
24828
|
-
|
|
25299
|
+
const snapshot = snapshotSkillsEnvironment(env);
|
|
25300
|
+
const resolved = resolveSkillsFleetOrThrow(snapshot, snapshotSkillsOptions(env, options));
|
|
25301
|
+
if (resolved.mode === "local" && env === process.env)
|
|
25302
|
+
noticeLocalSkillsMode();
|
|
25303
|
+
return resolved;
|
|
24829
25304
|
} catch (error) {
|
|
24830
25305
|
const translated = asSkillsFleetCredentialError(error);
|
|
24831
25306
|
if (translated)
|
|
@@ -24833,38 +25308,49 @@ function resolveSkillsFleet(env = process.env, options = {}) {
|
|
|
24833
25308
|
throw error;
|
|
24834
25309
|
}
|
|
24835
25310
|
}
|
|
24836
|
-
function
|
|
24837
|
-
|
|
24838
|
-
|
|
24839
|
-
|
|
24840
|
-
|
|
24841
|
-
|
|
24842
|
-
|
|
24843
|
-
const configured2 = configuredSkillsApiUrl(env, options.credentials?.keychain);
|
|
24844
|
-
const credential2 = resolveCredential(SKILLS_APP, env, options.credentials);
|
|
24845
|
-
if (!configured2 && !credential2) {
|
|
24846
|
-
if (env === process.env)
|
|
24847
|
-
noticeLocalSkillsMode();
|
|
24848
|
-
return { mode: "local", apiOrigin: null, apiKey: null };
|
|
24849
|
-
}
|
|
24850
|
-
if (configured2 && !credential2) {
|
|
24851
|
-
throw new SkillsFleetCredentialError(`${configured2.source} points this CLI at a Skills service but no API key resolved \u2014 ` + `refusing to run locally instead. Looked in the Keychain item ` + `hasna.credentials.${SKILLS_APP}.api-key, then ${skillsCredentialFiles(env).join(" or ") || "no credentials file (no HOME)"}, ` + `then ${SKILLS_API_KEY_ENV}. Sign in with: skills auth login`);
|
|
25311
|
+
function snapshotSkillsEnvironment(env) {
|
|
25312
|
+
const snapshot = {};
|
|
25313
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(env))) {
|
|
25314
|
+
if (!("value" in descriptor)) {
|
|
25315
|
+
if (/^(?:HASNA_|SKILLS_|HOME$|USER$)/.test(key))
|
|
25316
|
+
throw new SkillsFleetCredentialError("Accessor-backed Skills configuration is unsupported");
|
|
25317
|
+
continue;
|
|
24852
25318
|
}
|
|
24853
|
-
|
|
25319
|
+
snapshot[key] = descriptor.value;
|
|
24854
25320
|
}
|
|
24855
|
-
|
|
24856
|
-
|
|
25321
|
+
return Object.freeze(snapshot);
|
|
25322
|
+
}
|
|
25323
|
+
function snapshotSkillsOptions(env, options) {
|
|
25324
|
+
if (env !== process.env)
|
|
25325
|
+
return options;
|
|
25326
|
+
return { ...options, credentials: { ...options.credentials, keychain: {
|
|
25327
|
+
...options.credentials?.keychain,
|
|
25328
|
+
enabled: options.credentials?.keychain?.enabled ?? true
|
|
25329
|
+
} } };
|
|
25330
|
+
}
|
|
25331
|
+
function resolveSkillsFleetOrThrow(env, options) {
|
|
25332
|
+
if (selectsSkillsLocalMode(env))
|
|
25333
|
+
return { mode: "local", apiOrigin: null, apiKey: null };
|
|
25334
|
+
const assertFilesUnchanged = captureSkillsCredentialFiles(skillsProfileCredentialFiles(env, options.credentials?.profile));
|
|
25335
|
+
const configured = configuredSkillsApiUrl(env, options.credentials?.keychain, options.credentials?.profile);
|
|
24857
25336
|
const credential = resolveCredential(SKILLS_APP, env, options.credentials);
|
|
24858
25337
|
if (!credential) {
|
|
24859
|
-
|
|
25338
|
+
if (!configured) {
|
|
25339
|
+
throw new SkillsFleetCredentialError(`No API key resolved and no Skills API URL is configured \u2014 failing closed ` + `(local mode is opt-in only: set ${SKILLS_LOCAL_OPT_IN_ENV_KEYS[0]}=1 to run on this machine). ` + `Looked in ${credentialLocations(env)}. Sign in with: skills auth login`);
|
|
25340
|
+
}
|
|
25341
|
+
throw new SkillsFleetCredentialError(`${configured.source} points this CLI at a Skills service but no API key resolved \u2014 refusing to run locally instead. ` + `Looked in ${credentialLocations(env)}. Sign in with: skills auth login`);
|
|
24860
25342
|
}
|
|
25343
|
+
const apiOrigin = normalizeSkillsApiOrigin(configured?.value ?? defaultFleetGatewayBaseUrl(SKILLS_APP));
|
|
25344
|
+
toV1BaseUrl(apiOrigin);
|
|
25345
|
+
assertCredentialInstance(credential, apiOrigin, env, options);
|
|
25346
|
+
assertFilesUnchanged();
|
|
24861
25347
|
const base = {
|
|
24862
25348
|
mode: "hosted",
|
|
24863
25349
|
apiOrigin,
|
|
24864
|
-
apiUrlSource:
|
|
24865
|
-
apiKeySource:
|
|
24866
|
-
apiKeyTier:
|
|
24867
|
-
warning:
|
|
25350
|
+
apiUrlSource: configured?.source ?? "default",
|
|
25351
|
+
apiKeySource: credential.source,
|
|
25352
|
+
apiKeyTier: credential.tier,
|
|
25353
|
+
warning: credential.warning
|
|
24868
25354
|
};
|
|
24869
25355
|
if (credential.tier === "pointer") {
|
|
24870
25356
|
return { ...base, apiKey: null, apiKeyPointer: credential };
|
|
@@ -24874,19 +25360,41 @@ function resolveSkillsFleetOrThrow(env, options) {
|
|
|
24874
25360
|
}
|
|
24875
25361
|
return { ...base, apiKey: credential.apiKey, apiKeyPointer: null };
|
|
24876
25362
|
}
|
|
25363
|
+
function credentialLocations(env) {
|
|
25364
|
+
const files = skillsCredentialFiles(env).join(" or ") || "no credentials file (HOME is unset)";
|
|
25365
|
+
return `hasna.credentials.${SKILLS_APP}.api-key (macOS Keychain, account HASNA_STATION or the host name), ${files}, and ${SKILLS_API_KEY_ENV}`;
|
|
25366
|
+
}
|
|
25367
|
+
function assertCredentialInstance(credential, apiOrigin, env, options) {
|
|
25368
|
+
let bound;
|
|
25369
|
+
if (credential.tier === "disk" || credential.tier === "profile") {
|
|
25370
|
+
const metadata = readSkillsInstanceMetadata(credential.source);
|
|
25371
|
+
bound = metadata.binding ?? metadata.apiUrl ?? defaultFleetGatewayBaseUrl(SKILLS_APP);
|
|
25372
|
+
} else if (credential.tier === "keychain") {
|
|
25373
|
+
bound = keychainConfigValue(SKILLS_APP, env, options.credentials?.keychain)?.value ?? defaultFleetGatewayBaseUrl(SKILLS_APP);
|
|
25374
|
+
}
|
|
25375
|
+
if (bound && normalizeSkillsApiOrigin(bound) !== apiOrigin) {
|
|
25376
|
+
throw new SkillsFleetCredentialError("The selected Skills API does not match this credential's instance. Select its profile or sign in to the new instance; no credential was sent.", "INSTANCE_CREDENTIAL_MISMATCH");
|
|
25377
|
+
}
|
|
25378
|
+
}
|
|
24877
25379
|
async function resolveSkillsApiKey(env = process.env, options = {}) {
|
|
24878
|
-
|
|
25380
|
+
return (await resolveSkillsConnection(env, options))?.apiKey ?? null;
|
|
25381
|
+
}
|
|
25382
|
+
async function resolveSkillsConnection(env = process.env, options = {}) {
|
|
25383
|
+
const snapshotEnv = snapshotSkillsEnvironment(env);
|
|
25384
|
+
const fleet = resolveSkillsFleet(snapshotEnv, snapshotSkillsOptions(env, options));
|
|
25385
|
+
if (fleet.mode === "local" && env === process.env)
|
|
25386
|
+
noticeLocalSkillsMode();
|
|
24879
25387
|
if (fleet.mode !== "hosted")
|
|
24880
25388
|
return null;
|
|
24881
25389
|
if (fleet.apiKey)
|
|
24882
|
-
return fleet.apiKey;
|
|
25390
|
+
return { ...fleet, apiKey: fleet.apiKey };
|
|
24883
25391
|
const pointer = fleet.apiKeyPointer;
|
|
24884
25392
|
if (!pointer) {
|
|
24885
25393
|
throw new SkillsFleetCredentialError(`A Skills authority resolved but no API key did. Sign in with: skills auth login`);
|
|
24886
25394
|
}
|
|
24887
25395
|
let completed;
|
|
24888
25396
|
try {
|
|
24889
|
-
completed = await completePointerCredential(SKILLS_APP, pointer,
|
|
25397
|
+
completed = await completePointerCredential(SKILLS_APP, pointer, snapshotEnv);
|
|
24890
25398
|
} catch (error) {
|
|
24891
25399
|
const translated = asSkillsFleetCredentialError(error);
|
|
24892
25400
|
if (translated)
|
|
@@ -24896,7 +25404,7 @@ async function resolveSkillsApiKey(env = process.env, options = {}) {
|
|
|
24896
25404
|
if (!completed.apiKey?.trim()) {
|
|
24897
25405
|
throw new SkillsFleetCredentialError(`${credentialPointerEnvKey(SKILLS_APP)} names a vault item that produced an empty Skills API key \u2014 ` + `refusing to send an unauthenticated request.`);
|
|
24898
25406
|
}
|
|
24899
|
-
return completed.apiKey;
|
|
25407
|
+
return { ...fleet, apiKey: completed.apiKey, apiKeyPointer: null };
|
|
24900
25408
|
}
|
|
24901
25409
|
async function requireSkillsApiKey(action = "This command", env = process.env, options = {}) {
|
|
24902
25410
|
const apiKey = await resolveSkillsApiKey(env, options);
|
|
@@ -24904,27 +25412,31 @@ async function requireSkillsApiKey(action = "This command", env = process.env, o
|
|
|
24904
25412
|
throw new MissingSkillsFleetError(action);
|
|
24905
25413
|
return apiKey;
|
|
24906
25414
|
}
|
|
24907
|
-
function stripV1(baseUrl) {
|
|
24908
|
-
return baseUrl.replace(/\/v1$/, "").replace(/\/+$/, "");
|
|
24909
|
-
}
|
|
24910
25415
|
async function skillsCredentialOrReason(env = process.env, options = {}) {
|
|
24911
25416
|
try {
|
|
24912
|
-
const
|
|
24913
|
-
return
|
|
25417
|
+
const connection = await resolveSkillsConnection(env, options);
|
|
25418
|
+
return connection ? { apiKey: connection.apiKey, apiOrigin: connection.apiOrigin, reason: null } : { apiKey: null, apiOrigin: null, reason: null };
|
|
24914
25419
|
} catch (error) {
|
|
24915
|
-
if (error
|
|
24916
|
-
return { apiKey: null, reason: error.message };
|
|
25420
|
+
if (isSkillsFleetCredentialError(error)) {
|
|
25421
|
+
return { apiKey: null, apiOrigin: null, reason: error.message };
|
|
24917
25422
|
}
|
|
24918
25423
|
throw error;
|
|
24919
25424
|
}
|
|
24920
25425
|
}
|
|
24921
25426
|
function resolveSkillsApiOrigin(env = process.env, options = {}) {
|
|
24922
|
-
const configured = configuredSkillsApiUrl(env, options.credentials?.keychain);
|
|
25427
|
+
const configured = configuredSkillsApiUrl(env, options.credentials?.keychain, options.credentials?.profile);
|
|
24923
25428
|
if (configured) {
|
|
24924
25429
|
toV1BaseUrl(configured.value);
|
|
24925
25430
|
return { origin: normalizeSkillsApiOrigin(configured.value), source: configured.source };
|
|
24926
25431
|
}
|
|
24927
|
-
|
|
25432
|
+
let fleet;
|
|
25433
|
+
try {
|
|
25434
|
+
fleet = resolveSkillsFleet(env, options);
|
|
25435
|
+
} catch (error) {
|
|
25436
|
+
if (isSkillsFleetCredentialError(error))
|
|
25437
|
+
return null;
|
|
25438
|
+
throw error;
|
|
25439
|
+
}
|
|
24928
25440
|
return fleet.mode === "hosted" ? { origin: fleet.apiOrigin, source: fleet.apiUrlSource } : null;
|
|
24929
25441
|
}
|
|
24930
25442
|
function requireSkillsApiOrigin(action = "This command", env = process.env, options = {}) {
|
|
@@ -24950,7 +25462,7 @@ class MissingSkillsFleetError extends Error {
|
|
|
24950
25462
|
// package.json
|
|
24951
25463
|
var package_default = {
|
|
24952
25464
|
name: "@hasna/skills",
|
|
24953
|
-
version: "0.
|
|
25465
|
+
version: "0.5.0",
|
|
24954
25466
|
description: "Skills library for AI coding agents",
|
|
24955
25467
|
type: "module",
|
|
24956
25468
|
bin: {
|
|
@@ -24982,6 +25494,7 @@ var package_default = {
|
|
|
24982
25494
|
files: [
|
|
24983
25495
|
"dist/",
|
|
24984
25496
|
"!dist/**/*.test.d.ts",
|
|
25497
|
+
"!dist/**/*.fixture.d.ts",
|
|
24985
25498
|
"!dist/test-preload.d.ts",
|
|
24986
25499
|
"!dist/platform",
|
|
24987
25500
|
"bin/",
|
|
@@ -25007,10 +25520,10 @@ var package_default = {
|
|
|
25007
25520
|
migrate: "bun run ./src/server/migrate.ts",
|
|
25008
25521
|
typecheck: "tsc --noEmit",
|
|
25009
25522
|
"verify:release": "bun run scripts/release-guard.ts",
|
|
25523
|
+
"verify:consumer-types": "bun run scripts/consumer-types.ts",
|
|
25010
25524
|
prepare: "bun run build:js",
|
|
25011
|
-
prepack: "bun run build && bun run verify:release",
|
|
25012
|
-
prepublishOnly: "bun run typecheck && bun run test"
|
|
25013
|
-
postinstall: "mkdir -p $HOME/.hasna/skills/custom 2>/dev/null || true"
|
|
25525
|
+
prepack: "bun run build && bun run verify:release && bun run verify:consumer-types",
|
|
25526
|
+
prepublishOnly: "bun run typecheck && bun run test"
|
|
25014
25527
|
},
|
|
25015
25528
|
keywords: [
|
|
25016
25529
|
"skills",
|
|
@@ -25031,6 +25544,7 @@ var package_default = {
|
|
|
25031
25544
|
author: "Hasna",
|
|
25032
25545
|
license: "Apache-2.0",
|
|
25033
25546
|
devDependencies: {
|
|
25547
|
+
"@hasna/contracts": "1.0.2",
|
|
25034
25548
|
"@types/bun": "1.3.14",
|
|
25035
25549
|
"@types/node": "25.2.3",
|
|
25036
25550
|
"@types/react": "^18.2.0",
|
|
@@ -25042,8 +25556,7 @@ var package_default = {
|
|
|
25042
25556
|
dependencies: {
|
|
25043
25557
|
"@aws-sdk/client-ecs": "^3.1079.0",
|
|
25044
25558
|
"@aws-sdk/client-s3": "^3.1079.0",
|
|
25045
|
-
"@hasna/
|
|
25046
|
-
"@hasna/events": "0.1.16",
|
|
25559
|
+
"@hasna/events": "0.1.18",
|
|
25047
25560
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
25048
25561
|
chalk: "^5.3.0",
|
|
25049
25562
|
commander: "^12.1.0",
|
|
@@ -25859,8 +26372,8 @@ var $NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS = NODE_RESPONSE_CHECKSUM_V
|
|
|
25859
26372
|
var $getFlexibleChecksumsPlugin = getFlexibleChecksumsPlugin;
|
|
25860
26373
|
var $resolveFlexibleChecksumsConfig = resolveFlexibleChecksumsConfig;
|
|
25861
26374
|
|
|
25862
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
25863
|
-
var
|
|
26375
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/S3Client.js
|
|
26376
|
+
var import_client26 = __toESM(require_client2(), 1);
|
|
25864
26377
|
|
|
25865
26378
|
// ../../node_modules/.bun/@aws-sdk+middleware-sdk-s3@3.972.75/node_modules/@aws-sdk/middleware-sdk-s3/dist-cjs/submodules/s3/index.js
|
|
25866
26379
|
var { NoOpLogger, getSmithyContext } = require_client();
|
|
@@ -26467,9 +26980,9 @@ var $getThrow200ExceptionsPlugin = getThrow200ExceptionsPlugin;
|
|
|
26467
26980
|
var $getValidateBucketNamePlugin = getValidateBucketNamePlugin;
|
|
26468
26981
|
var $resolveS3Config = resolveS3Config;
|
|
26469
26982
|
|
|
26470
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
26983
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/S3Client.js
|
|
26471
26984
|
var import_core = __toESM(require_dist_cjs2(), 1);
|
|
26472
|
-
var
|
|
26985
|
+
var import_client27 = __toESM(require_client(), 1);
|
|
26473
26986
|
var import_config29 = __toESM(require_config(), 1);
|
|
26474
26987
|
var import_endpoints5 = __toESM(require_endpoints(), 1);
|
|
26475
26988
|
var import_event_streams2 = __toESM(require_event_streams(), 1);
|
|
@@ -26477,17 +26990,17 @@ var import_protocols6 = __toESM(require_protocols(), 1);
|
|
|
26477
26990
|
var import_retry4 = __toESM(require_retry(), 1);
|
|
26478
26991
|
var import_schema2 = __toESM(require_schema(), 1);
|
|
26479
26992
|
|
|
26480
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
26993
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/auth/httpAuthSchemeProvider.js
|
|
26481
26994
|
var import_httpAuthSchemes = __toESM(require_httpAuthSchemes(), 1);
|
|
26482
26995
|
var import_signature_v4_multi_region = __toESM(require_dist_cjs4(), 1);
|
|
26483
|
-
var
|
|
26996
|
+
var import_client5 = __toESM(require_client(), 1);
|
|
26484
26997
|
var import_endpoints3 = __toESM(require_endpoints(), 1);
|
|
26485
26998
|
|
|
26486
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
26487
|
-
var
|
|
26999
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/endpoint/endpointResolver.js
|
|
27000
|
+
var import_client4 = __toESM(require_client2(), 1);
|
|
26488
27001
|
var import_endpoints2 = __toESM(require_endpoints(), 1);
|
|
26489
27002
|
|
|
26490
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
27003
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/endpoint/bdd.js
|
|
26491
27004
|
var import_endpoints = __toESM(require_endpoints(), 1);
|
|
26492
27005
|
var aw = "ref";
|
|
26493
27006
|
var ax = "argv";
|
|
@@ -28431,7 +28944,7 @@ var nodes = new Int32Array([
|
|
|
28431
28944
|
]);
|
|
28432
28945
|
var bdd = import_endpoints.BinaryDecisionDiagram.from(nodes, root, _data.conditions, _data.results);
|
|
28433
28946
|
|
|
28434
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
28947
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/endpoint/endpointResolver.js
|
|
28435
28948
|
var cache = new import_endpoints2.EndpointCache({
|
|
28436
28949
|
size: 50,
|
|
28437
28950
|
params: [
|
|
@@ -28457,15 +28970,15 @@ var defaultEndpointResolver = (endpointParams, context = {}) => {
|
|
|
28457
28970
|
logger: context.logger
|
|
28458
28971
|
}));
|
|
28459
28972
|
};
|
|
28460
|
-
import_endpoints2.customEndpointFunctions.aws =
|
|
28973
|
+
import_endpoints2.customEndpointFunctions.aws = import_client4.awsEndpointFunctions;
|
|
28461
28974
|
|
|
28462
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
28975
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/auth/httpAuthSchemeProvider.js
|
|
28463
28976
|
var createEndpointRuleSetHttpAuthSchemeParametersProvider = (defaultHttpAuthSchemeParametersProvider) => async (config, context, input) => {
|
|
28464
28977
|
if (!input) {
|
|
28465
28978
|
throw new Error("Could not find `input` for `defaultEndpointRuleSetHttpAuthSchemeParametersProvider`");
|
|
28466
28979
|
}
|
|
28467
28980
|
const defaultParameters = await defaultHttpAuthSchemeParametersProvider(config, context, input);
|
|
28468
|
-
const instructionsFn =
|
|
28981
|
+
const instructionsFn = import_client5.getSmithyContext(context)?.commandInstance?.constructor?.getEndpointParameterInstructions;
|
|
28469
28982
|
if (!instructionsFn) {
|
|
28470
28983
|
throw new Error(`getEndpointParameterInstructions() is not defined on '${context.commandName}'`);
|
|
28471
28984
|
}
|
|
@@ -28474,8 +28987,8 @@ var createEndpointRuleSetHttpAuthSchemeParametersProvider = (defaultHttpAuthSche
|
|
|
28474
28987
|
};
|
|
28475
28988
|
var _defaultS3HttpAuthSchemeParametersProvider = async (config, context, input) => {
|
|
28476
28989
|
return {
|
|
28477
|
-
operation:
|
|
28478
|
-
region: await
|
|
28990
|
+
operation: import_client5.getSmithyContext(context).operation,
|
|
28991
|
+
region: await import_client5.normalizeProvider(config.region)() || (() => {
|
|
28479
28992
|
throw new Error("expected `region` to be configured for `aws.auth#sigv4`");
|
|
28480
28993
|
})()
|
|
28481
28994
|
};
|
|
@@ -28571,15 +29084,15 @@ var resolveHttpAuthSchemeConfig = (config) => {
|
|
|
28571
29084
|
const config_0 = import_httpAuthSchemes.resolveAwsSdkSigV4Config(config);
|
|
28572
29085
|
const config_1 = import_httpAuthSchemes.resolveAwsSdkSigV4AConfig(config_0);
|
|
28573
29086
|
return Object.assign(config_1, {
|
|
28574
|
-
authSchemePreference:
|
|
29087
|
+
authSchemePreference: import_client5.normalizeProvider(config.authSchemePreference ?? [])
|
|
28575
29088
|
});
|
|
28576
29089
|
};
|
|
28577
29090
|
|
|
28578
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
28579
|
-
var
|
|
29091
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/commandBuilder.js
|
|
29092
|
+
var import_client6 = __toESM(require_client(), 1);
|
|
28580
29093
|
var import_endpoints4 = __toESM(require_endpoints(), 1);
|
|
28581
29094
|
|
|
28582
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
29095
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/endpoint/EndpointParameters.js
|
|
28583
29096
|
var resolveClientEndpointParameters = (options) => {
|
|
28584
29097
|
return Object.assign(options, {
|
|
28585
29098
|
useFipsEndpoint: options.useFipsEndpoint ?? false,
|
|
@@ -28605,8 +29118,8 @@ var commonParams = {
|
|
|
28605
29118
|
UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" }
|
|
28606
29119
|
};
|
|
28607
29120
|
|
|
28608
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
28609
|
-
var command =
|
|
29121
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/commandBuilder.js
|
|
29122
|
+
var command = import_client6.makeBuilder(commonParams, "AmazonS3", "S3Client", import_endpoints4.getEndpointPlugin);
|
|
28610
29123
|
var _ep0 = {
|
|
28611
29124
|
Bucket: { type: "contextParams", name: "Bucket" },
|
|
28612
29125
|
Key: { type: "contextParams", name: "Key" }
|
|
@@ -28637,19 +29150,19 @@ var _mw11 = (Command, cs, config, o2) => [
|
|
|
28637
29150
|
$getSsecPlugin(config)
|
|
28638
29151
|
];
|
|
28639
29152
|
|
|
28640
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
29153
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/schemas/schemas_0.js
|
|
28641
29154
|
var import_schema = __toESM(require_schema(), 1);
|
|
28642
29155
|
|
|
28643
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
28644
|
-
var
|
|
28645
|
-
class S3ServiceException extends
|
|
29156
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/models/S3ServiceException.js
|
|
29157
|
+
var import_client7 = __toESM(require_client(), 1);
|
|
29158
|
+
class S3ServiceException extends import_client7.ServiceException {
|
|
28646
29159
|
constructor(options) {
|
|
28647
29160
|
super(options);
|
|
28648
29161
|
Object.setPrototypeOf(this, S3ServiceException.prototype);
|
|
28649
29162
|
}
|
|
28650
29163
|
}
|
|
28651
29164
|
|
|
28652
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
29165
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/models/errors.js
|
|
28653
29166
|
class NoSuchUpload extends S3ServiceException {
|
|
28654
29167
|
name = "NoSuchUpload";
|
|
28655
29168
|
$fault = "client";
|
|
@@ -28927,7 +29440,7 @@ class ObjectAlreadyInActiveTierError extends S3ServiceException {
|
|
|
28927
29440
|
}
|
|
28928
29441
|
}
|
|
28929
29442
|
|
|
28930
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
29443
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/schemas/schemas_0.js
|
|
28931
29444
|
var _A = "Account";
|
|
28932
29445
|
var _AAO = "AnalyticsAndOperator";
|
|
28933
29446
|
var _AC = "AccelerateConfiguration";
|
|
@@ -34379,13 +34892,13 @@ var WriteGetObjectResponse$ = [
|
|
|
34379
34892
|
() => __Unit
|
|
34380
34893
|
];
|
|
34381
34894
|
|
|
34382
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
34895
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/commands/CreateSessionCommand.js
|
|
34383
34896
|
class CreateSessionCommand extends command(_ep4, _mw0, "CreateSession", CreateSession$) {
|
|
34384
34897
|
}
|
|
34385
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
34898
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/package.json
|
|
34386
34899
|
var package_default2 = {
|
|
34387
34900
|
name: "@aws-sdk/client-s3",
|
|
34388
|
-
version: "3.
|
|
34901
|
+
version: "3.1127.0",
|
|
34389
34902
|
description: "AWS SDK for JavaScript S3 Client for Node.js, Browser and React Native",
|
|
34390
34903
|
homepage: "https://github.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3",
|
|
34391
34904
|
license: "Apache-2.0",
|
|
@@ -34452,7 +34965,7 @@ var package_default2 = {
|
|
|
34452
34965
|
tslib: "^2.6.2"
|
|
34453
34966
|
},
|
|
34454
34967
|
devDependencies: {
|
|
34455
|
-
"@aws-sdk/signature-v4-crt": "3.
|
|
34968
|
+
"@aws-sdk/signature-v4-crt": "3.1127.0",
|
|
34456
34969
|
"@smithy/snapshot-testing": "^2.3.2",
|
|
34457
34970
|
"@tsconfig/node20": "20.1.8",
|
|
34458
34971
|
"@types/node": "^20.14.8",
|
|
@@ -34467,8 +34980,8 @@ var package_default2 = {
|
|
|
34467
34980
|
}
|
|
34468
34981
|
};
|
|
34469
34982
|
|
|
34470
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
34471
|
-
var
|
|
34983
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
|
|
34984
|
+
var import_client22 = __toESM(require_client2(), 1);
|
|
34472
34985
|
var import_httpAuthSchemes3 = __toESM(require_httpAuthSchemes(), 1);
|
|
34473
34986
|
|
|
34474
34987
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-node@3.972.82/node_modules/@aws-sdk/credential-provider-node/dist-es/defaultProvider.js
|
|
@@ -34624,9 +35137,9 @@ var defaultProvider = (init = {}) => memoizeChain([
|
|
|
34624
35137
|
}
|
|
34625
35138
|
], credentialsTreatedAsExpired);
|
|
34626
35139
|
var credentialsTreatedAsExpired = (credentials) => credentials?.expiration !== undefined && credentials.expiration.getTime() - Date.now() < 300000;
|
|
34627
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
35140
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
|
|
34628
35141
|
var import_checksum2 = __toESM(require_checksum(), 1);
|
|
34629
|
-
var
|
|
35142
|
+
var import_client23 = __toESM(require_client(), 1);
|
|
34630
35143
|
var import_config28 = __toESM(require_config(), 1);
|
|
34631
35144
|
var import_event_streams = __toESM(require_event_streams(), 1);
|
|
34632
35145
|
var import_retry3 = __toESM(require_retry(), 1);
|
|
@@ -34862,11 +35375,11 @@ var subtle = typeof digest === "function" && typeof sign2 === "function" && type
|
|
|
34862
35375
|
var MAX_PENDING_BYTES = 8 * 1024 * 1024;
|
|
34863
35376
|
var $Sha1 = Sha1Node;
|
|
34864
35377
|
|
|
34865
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
35378
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.shared.js
|
|
34866
35379
|
var import_httpAuthSchemes2 = __toESM(require_httpAuthSchemes(), 1);
|
|
34867
35380
|
var import_signature_v4_multi_region2 = __toESM(require_dist_cjs4(), 1);
|
|
34868
35381
|
var import_checksum = __toESM(require_checksum(), 1);
|
|
34869
|
-
var
|
|
35382
|
+
var import_client21 = __toESM(require_client(), 1);
|
|
34870
35383
|
var import_protocols4 = __toESM(require_protocols(), 1);
|
|
34871
35384
|
var import_serde3 = __toESM(require_serde(), 1);
|
|
34872
35385
|
var getRuntimeConfig2 = (config) => {
|
|
@@ -34891,7 +35404,7 @@ var getRuntimeConfig2 = (config) => {
|
|
|
34891
35404
|
signer: new import_httpAuthSchemes2.AwsSdkSigV4ASigner
|
|
34892
35405
|
}
|
|
34893
35406
|
],
|
|
34894
|
-
logger: config?.logger ?? new
|
|
35407
|
+
logger: config?.logger ?? new import_client21.NoOpLogger,
|
|
34895
35408
|
md5: config?.md5 ?? import_checksum.Md5,
|
|
34896
35409
|
protocol: config?.protocol ?? $S3RestXmlProtocol,
|
|
34897
35410
|
protocolSettings: config?.protocolSettings ?? {
|
|
@@ -34914,13 +35427,13 @@ var getRuntimeConfig2 = (config) => {
|
|
|
34914
35427
|
};
|
|
34915
35428
|
};
|
|
34916
35429
|
|
|
34917
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
35430
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeConfig.js
|
|
34918
35431
|
var getRuntimeConfig3 = (config) => {
|
|
34919
|
-
|
|
35432
|
+
import_client23.emitWarningIfUnsupportedVersion(process.version);
|
|
34920
35433
|
const defaultsMode = import_config28.resolveDefaultsModeConfig(config);
|
|
34921
|
-
const defaultConfigProvider = () => defaultsMode().then(
|
|
35434
|
+
const defaultConfigProvider = () => defaultsMode().then(import_client23.loadConfigsForDefaultMode);
|
|
34922
35435
|
const clientSharedValues = getRuntimeConfig2(config);
|
|
34923
|
-
|
|
35436
|
+
import_client22.emitWarningIfUnsupportedVersion(process.version);
|
|
34924
35437
|
const loaderConfig = {
|
|
34925
35438
|
profile: config?.profile,
|
|
34926
35439
|
logger: clientSharedValues.logger
|
|
@@ -34933,7 +35446,7 @@ var getRuntimeConfig3 = (config) => {
|
|
|
34933
35446
|
authSchemePreference: config?.authSchemePreference ?? import_config28.loadConfig(import_httpAuthSchemes3.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig),
|
|
34934
35447
|
bodyLengthChecker: config?.bodyLengthChecker ?? import_serde4.calculateBodyLength,
|
|
34935
35448
|
credentialDefaultProvider: config?.credentialDefaultProvider ?? defaultProvider,
|
|
34936
|
-
defaultUserAgentProvider: config?.defaultUserAgentProvider ??
|
|
35449
|
+
defaultUserAgentProvider: config?.defaultUserAgentProvider ?? import_client22.createDefaultUserAgentProvider({ serviceId: clientSharedValues.serviceId, clientVersion: package_default2.version }),
|
|
34937
35450
|
disableS3ExpressSessionAuth: config?.disableS3ExpressSessionAuth ?? import_config28.loadConfig($NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS, loaderConfig),
|
|
34938
35451
|
eventStreamSerdeProvider: config?.eventStreamSerdeProvider ?? import_event_streams.eventStreamSerdeProvider,
|
|
34939
35452
|
maxAttempts: config?.maxAttempts ?? import_config28.loadConfig(import_retry3.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config),
|
|
@@ -34951,16 +35464,16 @@ var getRuntimeConfig3 = (config) => {
|
|
|
34951
35464
|
useArnRegion: config?.useArnRegion ?? import_config28.loadConfig($NODE_USE_ARN_REGION_CONFIG_OPTIONS, loaderConfig),
|
|
34952
35465
|
useDualstackEndpoint: config?.useDualstackEndpoint ?? import_config28.loadConfig(import_config28.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
|
|
34953
35466
|
useFipsEndpoint: config?.useFipsEndpoint ?? import_config28.loadConfig(import_config28.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
|
|
34954
|
-
userAgentAppId: config?.userAgentAppId ?? import_config28.loadConfig(
|
|
35467
|
+
userAgentAppId: config?.userAgentAppId ?? import_config28.loadConfig(import_client22.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig)
|
|
34955
35468
|
};
|
|
34956
35469
|
};
|
|
34957
35470
|
|
|
34958
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
34959
|
-
var
|
|
34960
|
-
var
|
|
35471
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeExtensions.js
|
|
35472
|
+
var import_client24 = __toESM(require_client2(), 1);
|
|
35473
|
+
var import_client25 = __toESM(require_client(), 1);
|
|
34961
35474
|
var import_protocols5 = __toESM(require_protocols(), 1);
|
|
34962
35475
|
|
|
34963
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
35476
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/auth/httpAuthExtensionConfiguration.js
|
|
34964
35477
|
var getHttpAuthExtensionConfiguration2 = (runtimeConfig) => {
|
|
34965
35478
|
const _httpAuthSchemes = runtimeConfig.httpAuthSchemes;
|
|
34966
35479
|
let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider;
|
|
@@ -34999,26 +35512,26 @@ var resolveHttpAuthRuntimeConfig2 = (config) => {
|
|
|
34999
35512
|
};
|
|
35000
35513
|
};
|
|
35001
35514
|
|
|
35002
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
35515
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/runtimeExtensions.js
|
|
35003
35516
|
var resolveRuntimeExtensions2 = (runtimeConfig, extensions) => {
|
|
35004
|
-
const extensionConfiguration = Object.assign(
|
|
35517
|
+
const extensionConfiguration = Object.assign(import_client24.getAwsRegionExtensionConfiguration(runtimeConfig), import_client25.getDefaultExtensionConfiguration(runtimeConfig), import_protocols5.getHttpHandlerExtensionConfiguration(runtimeConfig), getHttpAuthExtensionConfiguration2(runtimeConfig));
|
|
35005
35518
|
extensions.forEach((extension) => extension.configure(extensionConfiguration));
|
|
35006
|
-
return Object.assign(runtimeConfig,
|
|
35519
|
+
return Object.assign(runtimeConfig, import_client24.resolveAwsRegionExtensionConfiguration(extensionConfiguration), import_client25.resolveDefaultRuntimeConfig(extensionConfiguration), import_protocols5.resolveHttpHandlerRuntimeConfig(extensionConfiguration), resolveHttpAuthRuntimeConfig2(extensionConfiguration));
|
|
35007
35520
|
};
|
|
35008
35521
|
|
|
35009
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
35010
|
-
class S3Client extends
|
|
35522
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/S3Client.js
|
|
35523
|
+
class S3Client extends import_client27.Client {
|
|
35011
35524
|
config;
|
|
35012
35525
|
constructor(...[configuration]) {
|
|
35013
35526
|
const _config_0 = getRuntimeConfig3(configuration || {});
|
|
35014
35527
|
super(_config_0);
|
|
35015
35528
|
this.initConfig = _config_0;
|
|
35016
35529
|
const _config_1 = resolveClientEndpointParameters(_config_0);
|
|
35017
|
-
const _config_2 =
|
|
35530
|
+
const _config_2 = import_client26.resolveUserAgentConfig(_config_1);
|
|
35018
35531
|
const _config_3 = $resolveFlexibleChecksumsConfig(_config_2);
|
|
35019
35532
|
const _config_4 = import_retry4.resolveRetryConfig(_config_3);
|
|
35020
35533
|
const _config_5 = import_config29.resolveRegionConfig(_config_4);
|
|
35021
|
-
const _config_6 =
|
|
35534
|
+
const _config_6 = import_client26.resolveHostHeaderConfig(_config_5);
|
|
35022
35535
|
const _config_7 = import_endpoints5.resolveEndpointConfig(_config_6);
|
|
35023
35536
|
const _config_8 = import_event_streams2.resolveEventStreamSerdeConfig(_config_7);
|
|
35024
35537
|
const _config_9 = resolveHttpAuthSchemeConfig(_config_8);
|
|
@@ -35026,12 +35539,12 @@ class S3Client extends import_client25.Client {
|
|
|
35026
35539
|
const _config_11 = resolveRuntimeExtensions2(_config_10, configuration?.extensions || []);
|
|
35027
35540
|
this.config = _config_11;
|
|
35028
35541
|
this.middlewareStack.use(import_schema2.getSchemaSerdePlugin(this.config));
|
|
35029
|
-
this.middlewareStack.use(
|
|
35542
|
+
this.middlewareStack.use(import_client26.getUserAgentPlugin(this.config));
|
|
35030
35543
|
this.middlewareStack.use(import_retry4.getRetryPlugin(this.config));
|
|
35031
35544
|
this.middlewareStack.use(import_protocols6.getContentLengthPlugin(this.config));
|
|
35032
|
-
this.middlewareStack.use(
|
|
35033
|
-
this.middlewareStack.use(
|
|
35034
|
-
this.middlewareStack.use(
|
|
35545
|
+
this.middlewareStack.use(import_client26.getHostHeaderPlugin(this.config));
|
|
35546
|
+
this.middlewareStack.use(import_client26.getLoggerPlugin(this.config));
|
|
35547
|
+
this.middlewareStack.use(import_client26.getRecursionDetectionPlugin(this.config));
|
|
35035
35548
|
this.middlewareStack.use(import_core.getHttpAuthSchemeEndpointRuleSetPlugin(this.config, {
|
|
35036
35549
|
httpAuthSchemeParametersProvider: defaultS3HttpAuthSchemeParametersProvider,
|
|
35037
35550
|
identityProviderConfigProvider: async (config) => new import_core.DefaultIdentityProviderConfig({
|
|
@@ -35051,15 +35564,15 @@ class S3Client extends import_client25.Client {
|
|
|
35051
35564
|
}
|
|
35052
35565
|
}
|
|
35053
35566
|
|
|
35054
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
35567
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/commands/DeleteObjectCommand.js
|
|
35055
35568
|
class DeleteObjectCommand extends command(_ep0, _mw0, "DeleteObject", DeleteObject$) {
|
|
35056
35569
|
}
|
|
35057
35570
|
|
|
35058
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
35571
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/commands/GetObjectCommand.js
|
|
35059
35572
|
class GetObjectCommand extends command(_ep0, _mw7, "GetObject", GetObject$) {
|
|
35060
35573
|
}
|
|
35061
35574
|
|
|
35062
|
-
// ../../node_modules/.bun/@aws-sdk+client-s3@3.
|
|
35575
|
+
// ../../node_modules/.bun/@aws-sdk+client-s3@3.1127.0/node_modules/@aws-sdk/client-s3/dist-es/commands/PutObjectCommand.js
|
|
35063
35576
|
class PutObjectCommand extends command(_ep0, _mw11, "PutObject", PutObject$) {
|
|
35064
35577
|
}
|
|
35065
35578
|
|
|
@@ -35465,12 +35978,7 @@ import { homedir as homedir2 } from "os";
|
|
|
35465
35978
|
import { join as join4, resolve } from "path";
|
|
35466
35979
|
import { homedir as pathsResolverHomedir } from "os";
|
|
35467
35980
|
import { join as pathsResolverJoin } from "path";
|
|
35468
|
-
var
|
|
35469
|
-
config: "HASNA_CONFIG_HOME",
|
|
35470
|
-
data: "HASNA_DATA_HOME",
|
|
35471
|
-
state: "HASNA_STATE_HOME",
|
|
35472
|
-
cache: "HASNA_CACHE_HOME"
|
|
35473
|
-
};
|
|
35981
|
+
var PATHS_RESOLVER_DATA_ENV = "HASNA_DATA_HOME";
|
|
35474
35982
|
var PATHS_RESOLVER_APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
35475
35983
|
function pathsResolverAssertApp(app) {
|
|
35476
35984
|
if (typeof app !== "string" || app.length === 0) {
|
|
@@ -35480,48 +35988,19 @@ function pathsResolverAssertApp(app) {
|
|
|
35480
35988
|
throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
|
|
35481
35989
|
}
|
|
35482
35990
|
}
|
|
35483
|
-
function
|
|
35484
|
-
if (!Object.keys(PATHS_RESOLVER_KIND_ENV).includes(kind)) {
|
|
35485
|
-
throw new TypeError(`paths: invalid path kind "${kind}" \u2014 expected one of ${Object.keys(PATHS_RESOLVER_KIND_ENV).join(", ")}`);
|
|
35486
|
-
}
|
|
35487
|
-
}
|
|
35488
|
-
function pathsResolverBaseDir(kind, options) {
|
|
35489
|
-
pathsResolverAssertKind(kind);
|
|
35991
|
+
function pathsResolverDataBaseDir(options) {
|
|
35490
35992
|
const env = options.env ?? process.env;
|
|
35491
|
-
const override = env[
|
|
35993
|
+
const override = env[PATHS_RESOLVER_DATA_ENV];
|
|
35492
35994
|
if (typeof override === "string" && override.length > 0)
|
|
35493
35995
|
return override;
|
|
35494
35996
|
const home = options.home ?? pathsResolverHomedir();
|
|
35495
35997
|
const platform = options.platform ?? process.platform;
|
|
35496
|
-
|
|
35497
|
-
switch (kind) {
|
|
35498
|
-
case "config":
|
|
35499
|
-
case "data":
|
|
35500
|
-
return pathsResolverJoin(home, "Library", "Application Support", "Hasna");
|
|
35501
|
-
case "cache":
|
|
35502
|
-
return pathsResolverJoin(home, "Library", "Caches", "Hasna");
|
|
35503
|
-
case "state":
|
|
35504
|
-
return pathsResolverJoin(home, "Library", "Logs", "Hasna");
|
|
35505
|
-
}
|
|
35506
|
-
}
|
|
35507
|
-
switch (kind) {
|
|
35508
|
-
case "config":
|
|
35509
|
-
return pathsResolverJoin(home, ".config", "hasna");
|
|
35510
|
-
case "data":
|
|
35511
|
-
return pathsResolverJoin(home, ".local", "share", "hasna");
|
|
35512
|
-
case "state":
|
|
35513
|
-
return pathsResolverJoin(home, ".local", "state", "hasna");
|
|
35514
|
-
case "cache":
|
|
35515
|
-
return pathsResolverJoin(home, ".cache", "hasna");
|
|
35516
|
-
}
|
|
35998
|
+
return platform === "darwin" ? pathsResolverJoin(home, "Library", "Application Support", "Hasna") : pathsResolverJoin(home, ".local", "share", "hasna");
|
|
35517
35999
|
}
|
|
35518
|
-
function
|
|
36000
|
+
function dataDir(options) {
|
|
35519
36001
|
pathsResolverAssertApp(options.app);
|
|
35520
36002
|
const appSegment = options.internal === true ? pathsResolverJoin("internal", options.app) : options.app;
|
|
35521
|
-
return pathsResolverJoin(
|
|
35522
|
-
}
|
|
35523
|
-
function dataDir(options) {
|
|
35524
|
-
return pathsResolverResolve("data", options);
|
|
36003
|
+
return pathsResolverJoin(pathsResolverDataBaseDir(options), appSegment);
|
|
35525
36004
|
}
|
|
35526
36005
|
var DATA_DIR_ENV = "HASNA_SKILLS_DIR";
|
|
35527
36006
|
var HASNA_SKILLS_HOME_ENV = "HASNA_SKILLS_HOME";
|
|
@@ -36852,13 +37331,12 @@ class SqliteGovernanceStore {
|
|
|
36852
37331
|
return rows.map((row) => this.reservationFrom(row));
|
|
36853
37332
|
}
|
|
36854
37333
|
async reconcileReservation(reservationId2, actualCents, status) {
|
|
36855
|
-
const
|
|
36856
|
-
|
|
36857
|
-
|
|
36858
|
-
|
|
36859
|
-
this.db.
|
|
36860
|
-
|
|
36861
|
-
return this.reservationFrom(updated);
|
|
37334
|
+
const updated = this.db.query(`UPDATE skills_credit_reservations SET actual_cents = ?, status = ?, reconciled_at = ?
|
|
37335
|
+
WHERE id = ? AND status = 'reserved' RETURNING *`).get(actualCents, status, nowIso(), reservationId2);
|
|
37336
|
+
if (updated)
|
|
37337
|
+
return this.reservationFrom(updated);
|
|
37338
|
+
const existing = this.db.query("SELECT * FROM skills_credit_reservations WHERE id = ? LIMIT 1").get(reservationId2);
|
|
37339
|
+
return existing ? this.reservationFrom(existing) : null;
|
|
36862
37340
|
}
|
|
36863
37341
|
async monthlySpendCents(orgId, monthPrefix) {
|
|
36864
37342
|
const from = `${monthPrefix}-01T00:00:00.000Z`;
|
|
@@ -37046,6 +37524,7 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
37046
37524
|
import {
|
|
37047
37525
|
cpSync as cpSync3,
|
|
37048
37526
|
existsSync as existsSync9,
|
|
37527
|
+
lstatSync as lstatSync4,
|
|
37049
37528
|
mkdirSync as mkdirSync6,
|
|
37050
37529
|
mkdtempSync as mkdtempSync2,
|
|
37051
37530
|
readFileSync as readFileSync10,
|
|
@@ -37821,7 +38300,7 @@ var BRACE_SOURCE_EXCLUSION = new RegExp(`^!skills/\\{(${SLUG}(?:,${SLUG})+)\\}/s
|
|
|
37821
38300
|
var SINGLE_SOURCE_EXCLUSION = new RegExp(`^!skills/(${SLUG})/src$`);
|
|
37822
38301
|
|
|
37823
38302
|
// src/lib/skill-validation.ts
|
|
37824
|
-
import { existsSync as existsSync5, lstatSync, readFileSync as readFileSync7, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
38303
|
+
import { existsSync as existsSync5, lstatSync as lstatSync2, readFileSync as readFileSync7, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
37825
38304
|
import { isAbsolute as isAbsolute3, join as join10, normalize } from "path";
|
|
37826
38305
|
var VALID_SKILL_KINDS = ["executable", "instruction"];
|
|
37827
38306
|
var DOC_FILES = ["SKILL.md", "README.md", "CLAUDE.md"];
|
|
@@ -37902,6 +38381,16 @@ function isHostedMetadataSkill(skillName, frontmatter, registryMeta, packageDecl
|
|
|
37902
38381
|
return true;
|
|
37903
38382
|
return false;
|
|
37904
38383
|
}
|
|
38384
|
+
function frontmatterString(raw) {
|
|
38385
|
+
if (raw.startsWith('"') && raw.endsWith('"')) {
|
|
38386
|
+
try {
|
|
38387
|
+
const decoded = JSON.parse(raw);
|
|
38388
|
+
if (typeof decoded === "string")
|
|
38389
|
+
return decoded;
|
|
38390
|
+
} catch {}
|
|
38391
|
+
}
|
|
38392
|
+
return raw.replace(/^["']|["']$/g, "");
|
|
38393
|
+
}
|
|
37905
38394
|
function parseSkillFrontmatter(content) {
|
|
37906
38395
|
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
37907
38396
|
if (!match)
|
|
@@ -37921,12 +38410,12 @@ function parseSkillFrontmatter(content) {
|
|
|
37921
38410
|
const tags = [];
|
|
37922
38411
|
while (i3 + 1 < lines.length && /^\s+-\s+/.test(lines[i3 + 1])) {
|
|
37923
38412
|
i3++;
|
|
37924
|
-
tags.push(lines[i3].replace(/^\s+-\s+/, "").trim());
|
|
38413
|
+
tags.push(frontmatterString(lines[i3].replace(/^\s+-\s+/, "").trim()));
|
|
37925
38414
|
}
|
|
37926
38415
|
result.tags = tags;
|
|
37927
38416
|
continue;
|
|
37928
38417
|
}
|
|
37929
|
-
const value = rawValue
|
|
38418
|
+
const value = frontmatterString(rawValue);
|
|
37930
38419
|
if (!value)
|
|
37931
38420
|
continue;
|
|
37932
38421
|
if (key === "name")
|
|
@@ -37979,7 +38468,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
|
|
|
37979
38468
|
if (RESERVED_SKILL_ENTRIES.has(entry)) {
|
|
37980
38469
|
add(issues, "skill.reserved_file", `Reserved file '${entry}' is not allowed in skill packages`);
|
|
37981
38470
|
}
|
|
37982
|
-
if (
|
|
38471
|
+
if (lstatSync2(entryPath).isSymbolicLink()) {
|
|
37983
38472
|
add(issues, "skill.symlink_forbidden", `Symlink '${entry}' is not allowed in skill packages`);
|
|
37984
38473
|
}
|
|
37985
38474
|
if (!KNOWN_TOP_LEVEL_ENTRIES.has(entry)) {
|
|
@@ -38461,7 +38950,7 @@ function validateRuntimeContract(manifest, issues, strict) {
|
|
|
38461
38950
|
import {
|
|
38462
38951
|
cpSync,
|
|
38463
38952
|
existsSync as existsSync7,
|
|
38464
|
-
lstatSync as
|
|
38953
|
+
lstatSync as lstatSync3,
|
|
38465
38954
|
mkdirSync as mkdirSync4,
|
|
38466
38955
|
readFileSync as readFileSync9,
|
|
38467
38956
|
realpathSync,
|
|
@@ -38509,14 +38998,27 @@ function normalizePortableSkillName(name) {
|
|
|
38509
38998
|
}
|
|
38510
38999
|
return normalized;
|
|
38511
39000
|
}
|
|
39001
|
+
function normalizeNewPortableSkillName(name) {
|
|
39002
|
+
normalizePortableSkillName(name);
|
|
39003
|
+
const normalized = name.trim().replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
39004
|
+
if (!normalized)
|
|
39005
|
+
throw new Error(`Invalid skill name '${name}'. Include letters or numbers.`);
|
|
39006
|
+
return normalized;
|
|
39007
|
+
}
|
|
38512
39008
|
function readPortableSkillManifest(skillPath, fallbackName = basename(skillPath)) {
|
|
39009
|
+
return readManifest(skillPath, fallbackName, normalizePortableSkillName);
|
|
39010
|
+
}
|
|
39011
|
+
function readPortableSkillManifestForImport(skillPath) {
|
|
39012
|
+
return readManifest(skillPath, basename(skillPath), normalizeNewPortableSkillName);
|
|
39013
|
+
}
|
|
39014
|
+
function readManifest(skillPath, fallbackName, normalizeName) {
|
|
38513
39015
|
const skillJsonPath = join12(skillPath, "skill.json");
|
|
38514
39016
|
const skillMdPath = join12(skillPath, "SKILL.md");
|
|
38515
39017
|
const pkgPath = join12(skillPath, "package.json");
|
|
38516
39018
|
const jsonManifest = existsSync7(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
|
|
38517
39019
|
const frontmatter = existsSync7(skillMdPath) ? parseSkillFrontmatter(readFileSync9(skillMdPath, "utf-8")) ?? undefined : undefined;
|
|
38518
39020
|
const pkg = existsSync7(pkgPath) ? readJsonObject(pkgPath) : undefined;
|
|
38519
|
-
const name =
|
|
39021
|
+
const name = normalizeName(stringField(jsonManifest, "name") ?? frontmatter?.name ?? stringValue(pkg?.name) ?? fallbackName);
|
|
38520
39022
|
const description = stringField(jsonManifest, "description") ?? frontmatter?.description ?? stringValue(pkg?.description) ?? `${name} skill`;
|
|
38521
39023
|
const version2 = readDeclaredSkillVersion(skillPath) ?? PORTABLE_SKILL_DEFAULT_VERSION;
|
|
38522
39024
|
const kind = parseSkillKind(stringField(jsonManifest, "kind") ?? frontmatter?.kind);
|
|
@@ -38559,8 +39061,8 @@ function createInstructionManifest(name, options) {
|
|
|
38559
39061
|
description: options.description,
|
|
38560
39062
|
version: PORTABLE_SKILL_DEFAULT_VERSION,
|
|
38561
39063
|
displayName: displayName(name),
|
|
38562
|
-
category: "Development Tools",
|
|
38563
|
-
tags: ["custom", name],
|
|
39064
|
+
category: options.category ?? "Development Tools",
|
|
39065
|
+
tags: options.tags ?? ["custom", name],
|
|
38564
39066
|
kind: "instruction",
|
|
38565
39067
|
inputs: [],
|
|
38566
39068
|
commands: [],
|
|
@@ -38575,16 +39077,16 @@ function writeInstructionSkillTemplate(skillPath, manifest) {
|
|
|
38575
39077
|
}
|
|
38576
39078
|
function renderInstructionSkillMd(manifest) {
|
|
38577
39079
|
const tags = manifest.tags?.length ? `tags:
|
|
38578
|
-
${manifest.tags.map((tag) => ` - ${tag}`).join(`
|
|
39080
|
+
${manifest.tags.map((tag) => ` - ${yamlString(tag)}`).join(`
|
|
38579
39081
|
`)}
|
|
38580
39082
|
` : "";
|
|
38581
39083
|
return `---
|
|
38582
39084
|
name: ${manifest.name}
|
|
38583
|
-
description: ${manifest.description}
|
|
39085
|
+
description: ${yamlString(manifest.description)}
|
|
38584
39086
|
kind: instruction
|
|
38585
39087
|
version: ${manifest.version}
|
|
38586
39088
|
source: custom
|
|
38587
|
-
category: ${manifest.category ?? "Development Tools"}
|
|
39089
|
+
category: ${yamlString(manifest.category ?? "Development Tools")}
|
|
38588
39090
|
${tags}---
|
|
38589
39091
|
|
|
38590
39092
|
# ${manifest.displayName ?? displayName(manifest.name)}
|
|
@@ -38605,8 +39107,8 @@ function createPortableManifest(name, options) {
|
|
|
38605
39107
|
description: options.description,
|
|
38606
39108
|
version: PORTABLE_SKILL_DEFAULT_VERSION,
|
|
38607
39109
|
displayName: displayName(name),
|
|
38608
|
-
category: "Development Tools",
|
|
38609
|
-
tags: ["custom", name],
|
|
39110
|
+
category: options.category ?? "Development Tools",
|
|
39111
|
+
tags: options.tags ?? ["custom", name],
|
|
38610
39112
|
inputs: DEFAULT_INPUTS,
|
|
38611
39113
|
commands: [{
|
|
38612
39114
|
name,
|
|
@@ -38764,12 +39266,47 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
|
|
|
38764
39266
|
};
|
|
38765
39267
|
if (!existsSync7(join12(skillPath, "SKILL.md"))) {
|
|
38766
39268
|
writeFileSync2(join12(skillPath, "SKILL.md"), renderSkillMd(next));
|
|
39269
|
+
} else {
|
|
39270
|
+
const path = join12(skillPath, "SKILL.md");
|
|
39271
|
+
const content = readFileSync9(path, "utf8");
|
|
39272
|
+
const declaredName = parseSkillFrontmatter(content)?.name;
|
|
39273
|
+
if (declaredName && declaredName !== next.name) {
|
|
39274
|
+
writeFileSync2(path, renameInstructionFrontmatter(content, next.name));
|
|
39275
|
+
}
|
|
39276
|
+
}
|
|
39277
|
+
const packagePath = join12(skillPath, "package.json");
|
|
39278
|
+
if (existsSync7(packagePath)) {
|
|
39279
|
+
const pkg = readJsonObject(packagePath);
|
|
39280
|
+
if (typeof pkg.name === "string" && pkg.name !== next.name) {
|
|
39281
|
+
writeFileSync2(packagePath, `${JSON.stringify({ ...pkg, name: next.name }, null, 2)}
|
|
39282
|
+
`);
|
|
39283
|
+
}
|
|
38767
39284
|
}
|
|
38768
39285
|
writeSkillJsonWithHash(skillPath, next);
|
|
38769
39286
|
return readPortableSkillManifest(skillPath, next.name);
|
|
38770
39287
|
}
|
|
39288
|
+
function renameInstructionFrontmatter(content, name) {
|
|
39289
|
+
const frontmatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---(?=\r?\n|$)/);
|
|
39290
|
+
const names = frontmatter?.[1]?.match(/^[ \t]*name[ \t]*:[^\r\n]*/gm) ?? [];
|
|
39291
|
+
const declaration = names.length === 1 ? names[0].match(/^(name[ \t]*:[ \t]*)(.*?)([ \t]*)$/) : null;
|
|
39292
|
+
const scalar = declaration?.[2] ?? "";
|
|
39293
|
+
let simple = /^[a-zA-Z0-9_.@/ -]+$/.test(scalar);
|
|
39294
|
+
if (scalar.startsWith('"')) {
|
|
39295
|
+
try {
|
|
39296
|
+
simple = typeof JSON.parse(scalar) === "string";
|
|
39297
|
+
} catch {
|
|
39298
|
+
simple = false;
|
|
39299
|
+
}
|
|
39300
|
+
} else if (scalar.startsWith("'"))
|
|
39301
|
+
simple = /^'[^'\r\n]*'$/.test(scalar);
|
|
39302
|
+
if (!frontmatter || !declaration || !simple) {
|
|
39303
|
+
throw new Error("Cannot rename instruction SKILL.md: use one unambiguous top-level name scalar in frontmatter.");
|
|
39304
|
+
}
|
|
39305
|
+
const renamed = frontmatter[0].replace(/^name[ \t]*:[^\r\n]*/m, () => `${declaration[1]}${name}${declaration[3]}`);
|
|
39306
|
+
return renamed + content.slice(frontmatter[0].length);
|
|
39307
|
+
}
|
|
38771
39308
|
function copySkillDirectory(source, destination) {
|
|
38772
|
-
const resolvedSource =
|
|
39309
|
+
const resolvedSource = lstatSync3(source).isSymbolicLink() ? realpathSync(source) : source;
|
|
38773
39310
|
mkdirSync4(destination, { recursive: true });
|
|
38774
39311
|
cpSync(resolvedSource, destination, {
|
|
38775
39312
|
recursive: true,
|
|
@@ -38782,7 +39319,7 @@ function copySkillDirectory(source, destination) {
|
|
|
38782
39319
|
if (isExcludedCopyEntry(segments[i3], i3 === 0))
|
|
38783
39320
|
return false;
|
|
38784
39321
|
}
|
|
38785
|
-
if (
|
|
39322
|
+
if (lstatSync3(src).isSymbolicLink())
|
|
38786
39323
|
return false;
|
|
38787
39324
|
return true;
|
|
38788
39325
|
}
|
|
@@ -38797,10 +39334,13 @@ function isExcludedCopyEntry(name, isFirstSegment) {
|
|
|
38797
39334
|
return true;
|
|
38798
39335
|
return false;
|
|
38799
39336
|
}
|
|
39337
|
+
function yamlString(value) {
|
|
39338
|
+
return JSON.stringify(value);
|
|
39339
|
+
}
|
|
38800
39340
|
function renderSkillMd(manifest) {
|
|
38801
39341
|
return `---
|
|
38802
39342
|
name: ${manifest.name}
|
|
38803
|
-
description: ${manifest.description}
|
|
39343
|
+
description: ${yamlString(manifest.description)}
|
|
38804
39344
|
---
|
|
38805
39345
|
|
|
38806
39346
|
# ${manifest.displayName ?? displayName(manifest.name)}
|
|
@@ -39172,7 +39712,7 @@ function isOfficialSkillName(name) {
|
|
|
39172
39712
|
return OFFICIAL_SKILL_NAMES.has(name);
|
|
39173
39713
|
}
|
|
39174
39714
|
function scaffoldPortableSkill(name, options = {}) {
|
|
39175
|
-
const skillName =
|
|
39715
|
+
const skillName = normalizeNewPortableSkillName(name);
|
|
39176
39716
|
const root3 = getPortableSkillsRoot(options);
|
|
39177
39717
|
const skillPath = join13(root3, skillName);
|
|
39178
39718
|
if (existsSync8(skillPath)) {
|
|
@@ -39183,11 +39723,11 @@ function scaffoldPortableSkill(name, options = {}) {
|
|
|
39183
39723
|
const kind = options.kind ?? "executable";
|
|
39184
39724
|
const description = options.description ?? `${displayName(skillName)} skill`;
|
|
39185
39725
|
if (kind === "instruction") {
|
|
39186
|
-
const manifest2 = createInstructionManifest(skillName, { description });
|
|
39726
|
+
const manifest2 = createInstructionManifest(skillName, { description, category: options.category, tags: options.tags });
|
|
39187
39727
|
writeInstructionSkillTemplate(skillPath, manifest2);
|
|
39188
39728
|
return { name: skillName, path: skillPath, manifest: manifest2, created: true };
|
|
39189
39729
|
}
|
|
39190
|
-
const manifest = createPortableManifest(skillName, { description });
|
|
39730
|
+
const manifest = createPortableManifest(skillName, { description, category: options.category, tags: options.tags });
|
|
39191
39731
|
writePortableSkillTemplate(skillPath, manifest);
|
|
39192
39732
|
return { name: skillName, path: skillPath, manifest, created: true };
|
|
39193
39733
|
}
|
|
@@ -39242,9 +39782,9 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
39242
39782
|
if (!existsSync8(absoluteSource) || !statSync7(absoluteSource).isDirectory()) {
|
|
39243
39783
|
throw new Error(`Skill source directory not found: ${sourcePath}`);
|
|
39244
39784
|
}
|
|
39245
|
-
const inferred =
|
|
39785
|
+
const inferred = readPortableSkillManifestForImport(absoluteSource);
|
|
39246
39786
|
const explicitName = options.name != null;
|
|
39247
|
-
const skillName =
|
|
39787
|
+
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
39248
39788
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
39249
39789
|
const sourceSlug = safeNormalizeName(basename2(absoluteSource));
|
|
39250
39790
|
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename2(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
@@ -39518,6 +40058,20 @@ var SYNC_AGENTS = ["claude", "codewith", "codex", "opencode", "cursor"];
|
|
|
39518
40058
|
var SKILLS_SOURCE_ENV = "SKILLS_SOURCE";
|
|
39519
40059
|
var SYNC_MARKER_FILE = ".hasna-skills.json";
|
|
39520
40060
|
var SYNC_MARKER_MANAGED_BY = "@hasna/skills";
|
|
40061
|
+
function isSkillsOwnershipMarker(marker) {
|
|
40062
|
+
return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
|
|
40063
|
+
}
|
|
40064
|
+
function hasSkillsOwnershipMarker(dir) {
|
|
40065
|
+
const path = join14(dir, SYNC_MARKER_FILE);
|
|
40066
|
+
try {
|
|
40067
|
+
if (!lstatSync4(path).isFile())
|
|
40068
|
+
return false;
|
|
40069
|
+
const marker = JSON.parse(readFileSync10(path, "utf8"));
|
|
40070
|
+
return isSkillsOwnershipMarker(marker);
|
|
40071
|
+
} catch {
|
|
40072
|
+
return false;
|
|
40073
|
+
}
|
|
40074
|
+
}
|
|
39521
40075
|
function isSyncAgent(value) {
|
|
39522
40076
|
return SYNC_AGENTS.includes(value);
|
|
39523
40077
|
}
|
|
@@ -39701,7 +40255,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
|
|
|
39701
40255
|
const skillMdPath = join14(dir, "SKILL.md");
|
|
39702
40256
|
const markerPath = join14(dir, SYNC_MARKER_FILE);
|
|
39703
40257
|
const dirExists = existsSync9(dir);
|
|
39704
|
-
const managed =
|
|
40258
|
+
const managed = hasSkillsOwnershipMarker(dir);
|
|
39705
40259
|
const hasSkillMd = existsSync9(skillMdPath);
|
|
39706
40260
|
if (dirExists && !managed && !hasSkillMd) {
|
|
39707
40261
|
return {
|
|
@@ -39714,7 +40268,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
|
|
|
39714
40268
|
return {
|
|
39715
40269
|
action: "skip",
|
|
39716
40270
|
path: skillMdPath,
|
|
39717
|
-
reason: "an unmanaged SKILL.md already exists here (hand-authored); pass --force to overwrite"
|
|
40271
|
+
reason: existsSync9(markerPath) ? "an unmanaged SKILL.md already exists here (invalid or foreign ownership marker); pass --force to overwrite" : "an unmanaged SKILL.md already exists here (hand-authored); pass --force to overwrite"
|
|
39718
40272
|
};
|
|
39719
40273
|
}
|
|
39720
40274
|
if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
|
|
@@ -39791,7 +40345,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
|
|
|
39791
40345
|
}
|
|
39792
40346
|
function removeManagedAgentSkill(skill, agent, homeDir2 = homedir3()) {
|
|
39793
40347
|
const dir = join14(agentGlobalSkillsDir(agent, homeDir2), skill);
|
|
39794
|
-
if (!
|
|
40348
|
+
if (!hasSkillsOwnershipMarker(dir))
|
|
39795
40349
|
return false;
|
|
39796
40350
|
rmSync2(dir, { recursive: true, force: true });
|
|
39797
40351
|
return true;
|
|
@@ -40512,7 +41066,7 @@ function removeSkillForAgent(name, options) {
|
|
|
40512
41066
|
const canonicalName = getCanonicalSkillName(name);
|
|
40513
41067
|
const scope = options.scope ?? "global";
|
|
40514
41068
|
const dir = getAgentSkillPath(canonicalName, options.agent, scope, options.projectDir);
|
|
40515
|
-
if (!
|
|
41069
|
+
if (!hasSkillsOwnershipMarker(dir))
|
|
40516
41070
|
return false;
|
|
40517
41071
|
rmSync3(dir, { recursive: true, force: true });
|
|
40518
41072
|
return true;
|
|
@@ -40756,7 +41310,7 @@ async function runSkill(name, args, options = {}) {
|
|
|
40756
41310
|
}
|
|
40757
41311
|
const proc = Bun.spawn(["bun", "run", entryPath, ...args], {
|
|
40758
41312
|
cwd: skillPath,
|
|
40759
|
-
stdout: options.stdio === "pipe" ? "pipe" : "inherit",
|
|
41313
|
+
stdout: options.stdio === "pipe" ? "pipe" : options.stdio === "stderr" ? 2 : "inherit",
|
|
40760
41314
|
stderr: options.stdio === "pipe" ? "pipe" : "inherit",
|
|
40761
41315
|
stdin: "inherit",
|
|
40762
41316
|
env: { ...process.env, ...options.env }
|
|
@@ -41126,7 +41680,7 @@ async function getMergedSkill(store, artifactStorage, principal, slug) {
|
|
|
41126
41680
|
if (resolved.kind === "published")
|
|
41127
41681
|
return publishedPayload(resolved.record);
|
|
41128
41682
|
const bundled = getServerSkill(slug);
|
|
41129
|
-
return bundled ? bundled : null;
|
|
41683
|
+
return bundled ? { ...bundled, publicationState: "catalogue-only", revisionId: null } : null;
|
|
41130
41684
|
}
|
|
41131
41685
|
async function getMergedSkillMd(store, artifactStorage, principal, slug) {
|
|
41132
41686
|
const resolved = await resolvePublishedSkill(store, artifactStorage, principal, slug);
|
|
@@ -47090,7 +47644,7 @@ function sortKeys(value) {
|
|
|
47090
47644
|
return value.map(sortKeys);
|
|
47091
47645
|
if (value !== null && typeof value === "object") {
|
|
47092
47646
|
const record = value;
|
|
47093
|
-
const sorted =
|
|
47647
|
+
const sorted = Object.create(null);
|
|
47094
47648
|
for (const key of Object.keys(record).sort()) {
|
|
47095
47649
|
sorted[key] = sortKeys(record[key]);
|
|
47096
47650
|
}
|
|
@@ -47843,23 +48397,23 @@ function createReceiptService(store) {
|
|
|
47843
48397
|
// src/sdk/execution/dispatchers/ecs.ts
|
|
47844
48398
|
import { createHash as createHash11 } from "crypto";
|
|
47845
48399
|
|
|
47846
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
47847
|
-
var
|
|
48400
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/ECSClient.js
|
|
48401
|
+
var import_client36 = __toESM(require_client2(), 1);
|
|
47848
48402
|
var import_core2 = __toESM(require_dist_cjs2(), 1);
|
|
47849
|
-
var
|
|
48403
|
+
var import_client37 = __toESM(require_client(), 1);
|
|
47850
48404
|
var import_config39 = __toESM(require_config(), 1);
|
|
47851
48405
|
var import_endpoints8 = __toESM(require_endpoints(), 1);
|
|
47852
48406
|
var import_protocols10 = __toESM(require_protocols(), 1);
|
|
47853
48407
|
var import_retry6 = __toESM(require_retry(), 1);
|
|
47854
48408
|
var import_schema4 = __toESM(require_schema(), 1);
|
|
47855
48409
|
|
|
47856
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
48410
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/auth/httpAuthSchemeProvider.js
|
|
47857
48411
|
var import_httpAuthSchemes4 = __toESM(require_httpAuthSchemes(), 1);
|
|
47858
|
-
var
|
|
48412
|
+
var import_client28 = __toESM(require_client(), 1);
|
|
47859
48413
|
var defaultECSHttpAuthSchemeParametersProvider = async (config, context, input) => {
|
|
47860
48414
|
return {
|
|
47861
|
-
operation:
|
|
47862
|
-
region: await
|
|
48415
|
+
operation: import_client28.getSmithyContext(context).operation,
|
|
48416
|
+
region: await import_client28.normalizeProvider(config.region)() || (() => {
|
|
47863
48417
|
throw new Error("expected `region` to be configured for `aws.auth#sigv4`");
|
|
47864
48418
|
})()
|
|
47865
48419
|
};
|
|
@@ -47891,11 +48445,11 @@ var defaultECSHttpAuthSchemeProvider = (authParameters) => {
|
|
|
47891
48445
|
var resolveHttpAuthSchemeConfig3 = (config) => {
|
|
47892
48446
|
const config_0 = import_httpAuthSchemes4.resolveAwsSdkSigV4Config(config);
|
|
47893
48447
|
return Object.assign(config_0, {
|
|
47894
|
-
authSchemePreference:
|
|
48448
|
+
authSchemePreference: import_client28.normalizeProvider(config.authSchemePreference ?? [])
|
|
47895
48449
|
});
|
|
47896
48450
|
};
|
|
47897
48451
|
|
|
47898
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
48452
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/endpoint/EndpointParameters.js
|
|
47899
48453
|
var resolveClientEndpointParameters3 = (options) => {
|
|
47900
48454
|
return Object.assign(options, {
|
|
47901
48455
|
useDualstackEndpoint: options.useDualstackEndpoint ?? false,
|
|
@@ -47909,10 +48463,10 @@ var commonParams3 = {
|
|
|
47909
48463
|
Region: { type: "builtInParams", name: "region" },
|
|
47910
48464
|
UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" }
|
|
47911
48465
|
};
|
|
47912
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
48466
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/package.json
|
|
47913
48467
|
var package_default3 = {
|
|
47914
48468
|
name: "@aws-sdk/client-ecs",
|
|
47915
|
-
version: "3.
|
|
48469
|
+
version: "3.1127.0",
|
|
47916
48470
|
description: "AWS SDK for JavaScript Ecs Client for Node.js, Browser and React Native",
|
|
47917
48471
|
homepage: "https://github.com/aws/aws-sdk-js-v3/tree/main/clients/client-ecs",
|
|
47918
48472
|
license: "Apache-2.0",
|
|
@@ -47982,28 +48536,28 @@ var package_default3 = {
|
|
|
47982
48536
|
}
|
|
47983
48537
|
};
|
|
47984
48538
|
|
|
47985
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
47986
|
-
var
|
|
48539
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/runtimeConfig.js
|
|
48540
|
+
var import_client32 = __toESM(require_client2(), 1);
|
|
47987
48541
|
var import_httpAuthSchemes6 = __toESM(require_httpAuthSchemes(), 1);
|
|
47988
|
-
var
|
|
48542
|
+
var import_client33 = __toESM(require_client(), 1);
|
|
47989
48543
|
var import_config38 = __toESM(require_config(), 1);
|
|
47990
48544
|
var import_retry5 = __toESM(require_retry(), 1);
|
|
47991
48545
|
var import_serde6 = __toESM(require_serde(), 1);
|
|
47992
48546
|
var import_node_http_handler3 = __toESM(require_dist_cjs6(), 1);
|
|
47993
48547
|
|
|
47994
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
48548
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/runtimeConfig.shared.js
|
|
47995
48549
|
var import_httpAuthSchemes5 = __toESM(require_httpAuthSchemes(), 1);
|
|
47996
48550
|
var import_protocols7 = __toESM(require_protocols2(), 1);
|
|
47997
48551
|
var import_checksum3 = __toESM(require_checksum(), 1);
|
|
47998
|
-
var
|
|
48552
|
+
var import_client31 = __toESM(require_client(), 1);
|
|
47999
48553
|
var import_protocols8 = __toESM(require_protocols(), 1);
|
|
48000
48554
|
var import_serde5 = __toESM(require_serde(), 1);
|
|
48001
48555
|
|
|
48002
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
48003
|
-
var
|
|
48556
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/endpoint/endpointResolver.js
|
|
48557
|
+
var import_client29 = __toESM(require_client2(), 1);
|
|
48004
48558
|
var import_endpoints7 = __toESM(require_endpoints(), 1);
|
|
48005
48559
|
|
|
48006
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
48560
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/endpoint/bdd.js
|
|
48007
48561
|
var import_endpoints6 = __toESM(require_endpoints(), 1);
|
|
48008
48562
|
var k3 = "ref";
|
|
48009
48563
|
var a3 = -1;
|
|
@@ -48086,7 +48640,7 @@ var nodes3 = new Int32Array([
|
|
|
48086
48640
|
]);
|
|
48087
48641
|
var bdd3 = import_endpoints6.BinaryDecisionDiagram.from(nodes3, root3, _data3.conditions, _data3.results);
|
|
48088
48642
|
|
|
48089
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
48643
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/endpoint/endpointResolver.js
|
|
48090
48644
|
var cache3 = new import_endpoints7.EndpointCache({
|
|
48091
48645
|
size: 50,
|
|
48092
48646
|
params: ["Endpoint", "Region", "UseDualStack", "UseFIPS"]
|
|
@@ -48097,21 +48651,21 @@ var defaultEndpointResolver3 = (endpointParams, context = {}) => {
|
|
|
48097
48651
|
logger: context.logger
|
|
48098
48652
|
}));
|
|
48099
48653
|
};
|
|
48100
|
-
import_endpoints7.customEndpointFunctions.aws =
|
|
48654
|
+
import_endpoints7.customEndpointFunctions.aws = import_client29.awsEndpointFunctions;
|
|
48101
48655
|
|
|
48102
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
48656
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/schemas/schemas_0.js
|
|
48103
48657
|
var import_schema3 = __toESM(require_schema(), 1);
|
|
48104
48658
|
|
|
48105
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
48106
|
-
var
|
|
48107
|
-
class ECSServiceException extends
|
|
48659
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/models/ECSServiceException.js
|
|
48660
|
+
var import_client30 = __toESM(require_client(), 1);
|
|
48661
|
+
class ECSServiceException extends import_client30.ServiceException {
|
|
48108
48662
|
constructor(options) {
|
|
48109
48663
|
super(options);
|
|
48110
48664
|
Object.setPrototypeOf(this, ECSServiceException.prototype);
|
|
48111
48665
|
}
|
|
48112
48666
|
}
|
|
48113
48667
|
|
|
48114
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
48668
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/models/errors.js
|
|
48115
48669
|
class AccessDeniedException extends ECSServiceException {
|
|
48116
48670
|
name = "AccessDeniedException";
|
|
48117
48671
|
$fault = "client";
|
|
@@ -48504,7 +49058,7 @@ class BlockedException extends ECSServiceException {
|
|
|
48504
49058
|
}
|
|
48505
49059
|
}
|
|
48506
49060
|
|
|
48507
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
49061
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/schemas/schemas_0.js
|
|
48508
49062
|
var _A2 = "Attachment";
|
|
48509
49063
|
var _ACR = "AcceleratorCountRequest";
|
|
48510
49064
|
var _AD2 = "AttachmentDetails";
|
|
@@ -50891,7 +51445,7 @@ var StopTask$ = [
|
|
|
50891
51445
|
() => StopTaskResponse$
|
|
50892
51446
|
];
|
|
50893
51447
|
|
|
50894
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
51448
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/runtimeConfig.shared.js
|
|
50895
51449
|
var getRuntimeConfig4 = (config) => {
|
|
50896
51450
|
return {
|
|
50897
51451
|
apiVersion: "2014-11-13",
|
|
@@ -50908,7 +51462,7 @@ var getRuntimeConfig4 = (config) => {
|
|
|
50908
51462
|
signer: new import_httpAuthSchemes5.AwsSdkSigV4Signer
|
|
50909
51463
|
}
|
|
50910
51464
|
],
|
|
50911
|
-
logger: config?.logger ?? new
|
|
51465
|
+
logger: config?.logger ?? new import_client31.NoOpLogger,
|
|
50912
51466
|
protocol: config?.protocol ?? import_protocols7.AwsJson1_1Protocol,
|
|
50913
51467
|
protocolSettings: config?.protocolSettings ?? {
|
|
50914
51468
|
defaultNamespace: "com.amazonaws.ecs",
|
|
@@ -50925,13 +51479,13 @@ var getRuntimeConfig4 = (config) => {
|
|
|
50925
51479
|
};
|
|
50926
51480
|
};
|
|
50927
51481
|
|
|
50928
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
51482
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/runtimeConfig.js
|
|
50929
51483
|
var getRuntimeConfig5 = (config) => {
|
|
50930
|
-
|
|
51484
|
+
import_client33.emitWarningIfUnsupportedVersion(process.version);
|
|
50931
51485
|
const defaultsMode = import_config38.resolveDefaultsModeConfig(config);
|
|
50932
|
-
const defaultConfigProvider = () => defaultsMode().then(
|
|
51486
|
+
const defaultConfigProvider = () => defaultsMode().then(import_client33.loadConfigsForDefaultMode);
|
|
50933
51487
|
const clientSharedValues = getRuntimeConfig4(config);
|
|
50934
|
-
|
|
51488
|
+
import_client32.emitWarningIfUnsupportedVersion(process.version);
|
|
50935
51489
|
const loaderConfig = {
|
|
50936
51490
|
profile: config?.profile,
|
|
50937
51491
|
logger: clientSharedValues.logger
|
|
@@ -50944,7 +51498,7 @@ var getRuntimeConfig5 = (config) => {
|
|
|
50944
51498
|
authSchemePreference: config?.authSchemePreference ?? import_config38.loadConfig(import_httpAuthSchemes6.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig),
|
|
50945
51499
|
bodyLengthChecker: config?.bodyLengthChecker ?? import_serde6.calculateBodyLength,
|
|
50946
51500
|
credentialDefaultProvider: config?.credentialDefaultProvider ?? defaultProvider,
|
|
50947
|
-
defaultUserAgentProvider: config?.defaultUserAgentProvider ??
|
|
51501
|
+
defaultUserAgentProvider: config?.defaultUserAgentProvider ?? import_client32.createDefaultUserAgentProvider({ serviceId: clientSharedValues.serviceId, clientVersion: package_default3.version }),
|
|
50948
51502
|
maxAttempts: config?.maxAttempts ?? import_config38.loadConfig(import_retry5.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config),
|
|
50949
51503
|
region: config?.region ?? import_config38.loadConfig(import_config38.NODE_REGION_CONFIG_OPTIONS, { ...import_config38.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }),
|
|
50950
51504
|
requestHandler: import_node_http_handler3.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider),
|
|
@@ -50955,16 +51509,16 @@ var getRuntimeConfig5 = (config) => {
|
|
|
50955
51509
|
streamCollector: config?.streamCollector ?? import_node_http_handler3.streamCollector,
|
|
50956
51510
|
useDualstackEndpoint: config?.useDualstackEndpoint ?? import_config38.loadConfig(import_config38.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
|
|
50957
51511
|
useFipsEndpoint: config?.useFipsEndpoint ?? import_config38.loadConfig(import_config38.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
|
|
50958
|
-
userAgentAppId: config?.userAgentAppId ?? import_config38.loadConfig(
|
|
51512
|
+
userAgentAppId: config?.userAgentAppId ?? import_config38.loadConfig(import_client32.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig)
|
|
50959
51513
|
};
|
|
50960
51514
|
};
|
|
50961
51515
|
|
|
50962
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
50963
|
-
var
|
|
50964
|
-
var
|
|
51516
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/runtimeExtensions.js
|
|
51517
|
+
var import_client34 = __toESM(require_client2(), 1);
|
|
51518
|
+
var import_client35 = __toESM(require_client(), 1);
|
|
50965
51519
|
var import_protocols9 = __toESM(require_protocols(), 1);
|
|
50966
51520
|
|
|
50967
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
51521
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/auth/httpAuthExtensionConfiguration.js
|
|
50968
51522
|
var getHttpAuthExtensionConfiguration3 = (runtimeConfig) => {
|
|
50969
51523
|
const _httpAuthSchemes = runtimeConfig.httpAuthSchemes;
|
|
50970
51524
|
let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider;
|
|
@@ -51003,36 +51557,36 @@ var resolveHttpAuthRuntimeConfig3 = (config) => {
|
|
|
51003
51557
|
};
|
|
51004
51558
|
};
|
|
51005
51559
|
|
|
51006
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
51560
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/runtimeExtensions.js
|
|
51007
51561
|
var resolveRuntimeExtensions3 = (runtimeConfig, extensions) => {
|
|
51008
|
-
const extensionConfiguration = Object.assign(
|
|
51562
|
+
const extensionConfiguration = Object.assign(import_client34.getAwsRegionExtensionConfiguration(runtimeConfig), import_client35.getDefaultExtensionConfiguration(runtimeConfig), import_protocols9.getHttpHandlerExtensionConfiguration(runtimeConfig), getHttpAuthExtensionConfiguration3(runtimeConfig));
|
|
51009
51563
|
extensions.forEach((extension) => extension.configure(extensionConfiguration));
|
|
51010
|
-
return Object.assign(runtimeConfig,
|
|
51564
|
+
return Object.assign(runtimeConfig, import_client34.resolveAwsRegionExtensionConfiguration(extensionConfiguration), import_client35.resolveDefaultRuntimeConfig(extensionConfiguration), import_protocols9.resolveHttpHandlerRuntimeConfig(extensionConfiguration), resolveHttpAuthRuntimeConfig3(extensionConfiguration));
|
|
51011
51565
|
};
|
|
51012
51566
|
|
|
51013
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
51014
|
-
class ECSClient extends
|
|
51567
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/ECSClient.js
|
|
51568
|
+
class ECSClient extends import_client37.Client {
|
|
51015
51569
|
config;
|
|
51016
51570
|
constructor(...[configuration]) {
|
|
51017
51571
|
const _config_0 = getRuntimeConfig5(configuration || {});
|
|
51018
51572
|
super(_config_0);
|
|
51019
51573
|
this.initConfig = _config_0;
|
|
51020
51574
|
const _config_1 = resolveClientEndpointParameters3(_config_0);
|
|
51021
|
-
const _config_2 =
|
|
51575
|
+
const _config_2 = import_client36.resolveUserAgentConfig(_config_1);
|
|
51022
51576
|
const _config_3 = import_retry6.resolveRetryConfig(_config_2);
|
|
51023
51577
|
const _config_4 = import_config39.resolveRegionConfig(_config_3);
|
|
51024
|
-
const _config_5 =
|
|
51578
|
+
const _config_5 = import_client36.resolveHostHeaderConfig(_config_4);
|
|
51025
51579
|
const _config_6 = import_endpoints8.resolveEndpointConfig(_config_5);
|
|
51026
51580
|
const _config_7 = resolveHttpAuthSchemeConfig3(_config_6);
|
|
51027
51581
|
const _config_8 = resolveRuntimeExtensions3(_config_7, configuration?.extensions || []);
|
|
51028
51582
|
this.config = _config_8;
|
|
51029
51583
|
this.middlewareStack.use(import_schema4.getSchemaSerdePlugin(this.config));
|
|
51030
|
-
this.middlewareStack.use(
|
|
51584
|
+
this.middlewareStack.use(import_client36.getUserAgentPlugin(this.config));
|
|
51031
51585
|
this.middlewareStack.use(import_retry6.getRetryPlugin(this.config));
|
|
51032
51586
|
this.middlewareStack.use(import_protocols10.getContentLengthPlugin(this.config));
|
|
51033
|
-
this.middlewareStack.use(
|
|
51034
|
-
this.middlewareStack.use(
|
|
51035
|
-
this.middlewareStack.use(
|
|
51587
|
+
this.middlewareStack.use(import_client36.getHostHeaderPlugin(this.config));
|
|
51588
|
+
this.middlewareStack.use(import_client36.getLoggerPlugin(this.config));
|
|
51589
|
+
this.middlewareStack.use(import_client36.getRecursionDetectionPlugin(this.config));
|
|
51036
51590
|
this.middlewareStack.use(import_core2.getHttpAuthSchemeEndpointRuleSetPlugin(this.config, {
|
|
51037
51591
|
httpAuthSchemeParametersProvider: defaultECSHttpAuthSchemeParametersProvider,
|
|
51038
51592
|
identityProviderConfigProvider: async (config) => new import_core2.DefaultIdentityProviderConfig({
|
|
@@ -51046,26 +51600,26 @@ class ECSClient extends import_client35.Client {
|
|
|
51046
51600
|
}
|
|
51047
51601
|
}
|
|
51048
51602
|
|
|
51049
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
51050
|
-
var
|
|
51603
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/commandBuilder.js
|
|
51604
|
+
var import_client38 = __toESM(require_client(), 1);
|
|
51051
51605
|
var import_endpoints9 = __toESM(require_endpoints(), 1);
|
|
51052
|
-
var command3 =
|
|
51606
|
+
var command3 = import_client38.makeBuilder(commonParams3, "AmazonEC2ContainerServiceV20141113", "ECSClient", import_endpoints9.getEndpointPlugin);
|
|
51053
51607
|
var _ep03 = {};
|
|
51054
51608
|
var _mw03 = (Command, cs, config, o2) => [];
|
|
51055
51609
|
|
|
51056
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
51610
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/commands/DescribeTasksCommand.js
|
|
51057
51611
|
class DescribeTasksCommand extends command3(_ep03, _mw03, "DescribeTasks", DescribeTasks$) {
|
|
51058
51612
|
}
|
|
51059
51613
|
|
|
51060
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
51614
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/commands/ListTasksCommand.js
|
|
51061
51615
|
class ListTasksCommand extends command3(_ep03, _mw03, "ListTasks", ListTasks$) {
|
|
51062
51616
|
}
|
|
51063
51617
|
|
|
51064
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
51618
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/commands/RunTaskCommand.js
|
|
51065
51619
|
class RunTaskCommand extends command3(_ep03, _mw03, "RunTask", RunTask$) {
|
|
51066
51620
|
}
|
|
51067
51621
|
|
|
51068
|
-
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.
|
|
51622
|
+
// ../../node_modules/.bun/@aws-sdk+client-ecs@3.1127.0/node_modules/@aws-sdk/client-ecs/dist-es/commands/StopTaskCommand.js
|
|
51069
51623
|
class StopTaskCommand extends command3(_ep03, _mw03, "StopTask", StopTask$) {
|
|
51070
51624
|
}
|
|
51071
51625
|
|
|
@@ -51391,6 +51945,7 @@ var localRunExecutor = {
|
|
|
51391
51945
|
// src/sdk/storage.ts
|
|
51392
51946
|
var artifactStorageSeam = ArtifactStorage;
|
|
51393
51947
|
// src/sdk/outputs.ts
|
|
51948
|
+
import { createHash as createHash12 } from "crypto";
|
|
51394
51949
|
class DatabaseOnlyObjectStore {
|
|
51395
51950
|
usesS3 = false;
|
|
51396
51951
|
async materialize(run, artifact, body) {
|
|
@@ -51418,9 +51973,13 @@ function createGovernedArtifactWriter(options) {
|
|
|
51418
51973
|
const storage2 = options.storage ?? new DatabaseOnlyObjectStore;
|
|
51419
51974
|
return {
|
|
51420
51975
|
async write(run, meta, body) {
|
|
51976
|
+
if (typeof body?.bodyText !== "string") {
|
|
51977
|
+
throw new TypeError("Governed artifacts require a text body before persistence");
|
|
51978
|
+
}
|
|
51421
51979
|
const redacted = redactRunOutput(body.bodyText, config.redactPatterns);
|
|
51422
51980
|
const redactedBody = { ...body, bodyText: redacted };
|
|
51423
|
-
const
|
|
51981
|
+
const persistedBytes = new TextEncoder().encode(redacted);
|
|
51982
|
+
const outputBytes = persistedBytes.byteLength;
|
|
51424
51983
|
if (outputBytes > config.perOutputBytes) {
|
|
51425
51984
|
throw new GovernanceError(GOVERNANCE_ERROR_CODES.ARTIFACT_LIMIT_EXCEEDED, `output ${meta.relativePath} for run ${run.id} is ${outputBytes} bytes; the per-output limit is ${config.perOutputBytes}`, { gate: "perOutputBytes" });
|
|
51426
51985
|
}
|
|
@@ -51432,6 +51991,8 @@ function createGovernedArtifactWriter(options) {
|
|
|
51432
51991
|
const createdAt = new Date().toISOString();
|
|
51433
51992
|
const stamped = {
|
|
51434
51993
|
...meta,
|
|
51994
|
+
byteSize: outputBytes,
|
|
51995
|
+
sha256: createHash12("sha256").update(persistedBytes).digest("hex"),
|
|
51435
51996
|
visibility: options.visibility ?? config.defaultVisibility,
|
|
51436
51997
|
...config.artifactTtlSeconds !== undefined ? { expiresAt: expiresAtFor(createdAt, config.artifactTtlSeconds) } : {}
|
|
51437
51998
|
};
|
|
@@ -51603,6 +52164,1011 @@ function createOfflineGate(options) {
|
|
|
51603
52164
|
}
|
|
51604
52165
|
};
|
|
51605
52166
|
}
|
|
52167
|
+
// src/lib/remote-workspace.ts
|
|
52168
|
+
var record = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
52169
|
+
var cursor = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,512}$/.test(value);
|
|
52170
|
+
var uuid = (value) => typeof value === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(value);
|
|
52171
|
+
function workspaceMembersQuery(options = {}) {
|
|
52172
|
+
if (!record(options) || Object.keys(options).some((key) => key !== "limit" && key !== "cursor") || options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100) || options.cursor !== undefined && !cursor(options.cursor))
|
|
52173
|
+
throw new Error("Use a roster limit from 1 to 100 and an unchanged continuation cursor.");
|
|
52174
|
+
const query = new URLSearchParams;
|
|
52175
|
+
if (options.limit !== undefined)
|
|
52176
|
+
query.set("limit", String(options.limit));
|
|
52177
|
+
if (options.cursor !== undefined)
|
|
52178
|
+
query.set("cursor", options.cursor);
|
|
52179
|
+
return query.size ? `?${query}` : "";
|
|
52180
|
+
}
|
|
52181
|
+
function timestamp(value) {
|
|
52182
|
+
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}Z$/.test(value))
|
|
52183
|
+
return false;
|
|
52184
|
+
const time = Date.parse(value);
|
|
52185
|
+
return Number.isFinite(time) && new Date(time).toISOString().slice(0, 23) === value.slice(0, 23);
|
|
52186
|
+
}
|
|
52187
|
+
function parseMember(row, fail) {
|
|
52188
|
+
if (!record(row) || !uuid(row.membershipId) || !uuid(row.userId) || typeof row.email !== "string" || !row.email || !(row.displayName === null || typeof row.displayName === "string") || !isRole(row.role) || !timestamp(row.createdAt))
|
|
52189
|
+
return fail();
|
|
52190
|
+
return {
|
|
52191
|
+
membershipId: row.membershipId,
|
|
52192
|
+
userId: row.userId,
|
|
52193
|
+
email: row.email,
|
|
52194
|
+
displayName: row.displayName,
|
|
52195
|
+
role: row.role,
|
|
52196
|
+
createdAt: row.createdAt
|
|
52197
|
+
};
|
|
52198
|
+
}
|
|
52199
|
+
var isRole = (value) => typeof value === "string" && ["owner", "admin", "member", "viewer"].includes(value);
|
|
52200
|
+
|
|
52201
|
+
class WorkspaceMemberInputError extends Error {
|
|
52202
|
+
constructor() {
|
|
52203
|
+
super("Use an unchanged lowercase membership ID and the exact role and expected-role parameters from the roster.");
|
|
52204
|
+
this.name = "WorkspaceMemberInputError";
|
|
52205
|
+
}
|
|
52206
|
+
}
|
|
52207
|
+
function mutationInput(membershipId, input, roleChange) {
|
|
52208
|
+
if (typeof membershipId !== "string" || !uuid(membershipId) || membershipId !== membershipId.toLowerCase() || !record(input) || Object.keys(input).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
|
|
52209
|
+
throw new WorkspaceMemberInputError;
|
|
52210
|
+
const expectedRole = input.expectedRole, role = roleChange ? input.role : undefined;
|
|
52211
|
+
if (!isRole(expectedRole) || roleChange && !isRole(role))
|
|
52212
|
+
throw new WorkspaceMemberInputError;
|
|
52213
|
+
return { membershipId, role, expectedRole };
|
|
52214
|
+
}
|
|
52215
|
+
function workspaceMemberRoleInput(membershipId, input) {
|
|
52216
|
+
const value = mutationInput(membershipId, input, true);
|
|
52217
|
+
return { membershipId: value.membershipId, body: { role: value.role, expectedRole: value.expectedRole } };
|
|
52218
|
+
}
|
|
52219
|
+
function workspaceMemberRemovalInput(membershipId, input) {
|
|
52220
|
+
const value = mutationInput(membershipId, input, false);
|
|
52221
|
+
return { membershipId: value.membershipId, body: { expectedRole: value.expectedRole } };
|
|
52222
|
+
}
|
|
52223
|
+
var invalidMemberResult = "The server returned an invalid workspace member result. Refresh the roster before another action.";
|
|
52224
|
+
function parseWorkspaceMemberRoleResult(value, membershipId, role) {
|
|
52225
|
+
const fail = () => {
|
|
52226
|
+
throw new Error(invalidMemberResult);
|
|
52227
|
+
};
|
|
52228
|
+
if (!record(value) || !uuid(value.organizationId) || typeof value.changed !== "boolean")
|
|
52229
|
+
return fail();
|
|
52230
|
+
const member = parseMember(value.member, fail);
|
|
52231
|
+
if (member.membershipId !== membershipId || member.role !== role)
|
|
52232
|
+
return fail();
|
|
52233
|
+
return { organizationId: value.organizationId, member, changed: value.changed };
|
|
52234
|
+
}
|
|
52235
|
+
function parseWorkspaceMemberRemovalResult(value, membershipId) {
|
|
52236
|
+
if (!record(value) || !uuid(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
|
|
52237
|
+
throw new Error(invalidMemberResult);
|
|
52238
|
+
return { organizationId: value.organizationId, membershipId, removed: true, alreadyRemoved: value.alreadyRemoved };
|
|
52239
|
+
}
|
|
52240
|
+
var workspaceMemberFailures = {
|
|
52241
|
+
INVALID_REQUEST: [400, "Provide the exact membership role parameters."],
|
|
52242
|
+
ACCOUNT_UNAVAILABLE: [403, "Account is unavailable."],
|
|
52243
|
+
INTERACTIVE_SESSION_REQUIRED: [403, "Fresh interactive sign-in is required."],
|
|
52244
|
+
WORKSPACE_ADMIN_REQUIRED: [403, "A current workspace owner or admin is required."],
|
|
52245
|
+
MEMBERSHIP_ACTION_FORBIDDEN: [403, "Your current workspace role cannot perform this membership action."],
|
|
52246
|
+
MEMBERSHIP_NOT_FOUND: [404, "Membership was not found in the current workspace."],
|
|
52247
|
+
SELF_REMOVAL_UNAVAILABLE: [409, "Leaving your own workspace is not available through member removal."],
|
|
52248
|
+
MEMBERSHIP_ROLE_CHANGED: [409, "The member role changed. Refresh the roster before another action."],
|
|
52249
|
+
LAST_OWNER_REQUIRED: [409, "The workspace must retain at least one active owner."],
|
|
52250
|
+
MEMBERSHIP_BUSY: [503, "Membership is busy. Refresh the roster before another action."]
|
|
52251
|
+
};
|
|
52252
|
+
function workspaceMemberFailure(value, status) {
|
|
52253
|
+
if (!record(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
|
|
52254
|
+
return null;
|
|
52255
|
+
const code = value.code;
|
|
52256
|
+
return workspaceMemberFailures[code][0] === status ? code : null;
|
|
52257
|
+
}
|
|
52258
|
+
function parseWorkspaceMembersPage(value) {
|
|
52259
|
+
const fail = () => {
|
|
52260
|
+
throw new Error("The server returned an invalid workspace roster.");
|
|
52261
|
+
};
|
|
52262
|
+
if (!record(value) || !uuid(value.organizationId) || !Array.isArray(value.members) || value.members.length > 100 || !(value.nextCursor === null || cursor(value.nextCursor)) || !value.members.length && value.nextCursor !== null)
|
|
52263
|
+
return fail();
|
|
52264
|
+
const members = value.members.map((row) => parseMember(row, fail));
|
|
52265
|
+
if (new Set(members.map((row) => row.membershipId)).size !== members.length)
|
|
52266
|
+
return fail();
|
|
52267
|
+
return { organizationId: value.organizationId, members, nextCursor: value.nextCursor };
|
|
52268
|
+
}
|
|
52269
|
+
// src/lib/auth-store.ts
|
|
52270
|
+
function getApiUrl(action, env = process.env, options = {}) {
|
|
52271
|
+
return requireSkillsApiOrigin(action, env, options);
|
|
52272
|
+
}
|
|
52273
|
+
|
|
52274
|
+
// src/lib/remote-account.ts
|
|
52275
|
+
class RemoteCreditApprovalError extends Error {
|
|
52276
|
+
requiredCredits;
|
|
52277
|
+
maximumCredits;
|
|
52278
|
+
code = "CREDIT_APPROVAL_REQUIRED";
|
|
52279
|
+
constructor(requiredCredits, maximumCredits) {
|
|
52280
|
+
super(`This run requires ${requiredCredits} credits; the approved maximum is ${maximumCredits}. Quote the run and explicitly approve its cost.`);
|
|
52281
|
+
this.requiredCredits = requiredCredits;
|
|
52282
|
+
this.maximumCredits = maximumCredits;
|
|
52283
|
+
this.name = "RemoteCreditApprovalError";
|
|
52284
|
+
}
|
|
52285
|
+
}
|
|
52286
|
+
function creditCount(value) {
|
|
52287
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0 || value > 2147483647) {
|
|
52288
|
+
throw new Error("The Skills server returned an invalid credit count");
|
|
52289
|
+
}
|
|
52290
|
+
return value;
|
|
52291
|
+
}
|
|
52292
|
+
function parseRemoteRunQuote(value) {
|
|
52293
|
+
const quote = object(value);
|
|
52294
|
+
const pricing = object(quote.pricing);
|
|
52295
|
+
if (typeof quote.skill !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(quote.skill))
|
|
52296
|
+
throw new Error("Invalid quoted skill");
|
|
52297
|
+
const costCents = creditCount(pricing.costCredits ?? pricing.costCents);
|
|
52298
|
+
if (pricing.costCredits !== undefined && pricing.costCents !== undefined && pricing.costCents !== costCents)
|
|
52299
|
+
throw new Error("Inconsistent quoted credit count");
|
|
52300
|
+
if (quote.availability && object(quote.availability).status !== "available")
|
|
52301
|
+
throw new Error("This skill is unavailable for remote execution");
|
|
52302
|
+
return { ...quote, skill: quote.skill, pricing: { ...pricing, costCredits: costCents, costCents, formattedCost: `${costCents} credits` } };
|
|
52303
|
+
}
|
|
52304
|
+
function parseRemoteCreditPacks(value) {
|
|
52305
|
+
if (!Array.isArray(value))
|
|
52306
|
+
throw new Error("Invalid credit pack response");
|
|
52307
|
+
const ids = new Set;
|
|
52308
|
+
return value.map((value2) => {
|
|
52309
|
+
const row = object(value2);
|
|
52310
|
+
const counts = [row.credits, row.creditsCents, row.amountCents].filter((value3) => value3 !== undefined).map(creditCount);
|
|
52311
|
+
if (!counts.length || counts[0] === 0 || counts.some((count) => count !== counts[0]))
|
|
52312
|
+
throw new Error("Inconsistent credit pack counts");
|
|
52313
|
+
const credits = counts[0];
|
|
52314
|
+
const id = row.id ?? `credits_${credits}`;
|
|
52315
|
+
if (typeof id !== "string" || !/^[a-z0-9][a-z0-9_-]{0,99}$/.test(id) || ids.has(id))
|
|
52316
|
+
throw new Error("Invalid credit pack ID");
|
|
52317
|
+
if (id.startsWith("credits_") && id !== `credits_${credits}`)
|
|
52318
|
+
throw new Error("Inconsistent credit pack ID");
|
|
52319
|
+
ids.add(id);
|
|
52320
|
+
return { id, credits, ...row.expiresInDays === undefined ? {} : { expiresInDays: creditCount(row.expiresInDays) } };
|
|
52321
|
+
});
|
|
52322
|
+
}
|
|
52323
|
+
function parseRemoteBillingStatus(value) {
|
|
52324
|
+
const row = object(value);
|
|
52325
|
+
const counts = [row.creditBalance, row.balanceCents].filter((value2) => value2 !== undefined).map(creditCount);
|
|
52326
|
+
if (!counts.length || counts.some((count) => count !== counts[0]))
|
|
52327
|
+
throw new Error("Inconsistent credit balance");
|
|
52328
|
+
return {
|
|
52329
|
+
creditBalance: counts[0],
|
|
52330
|
+
formattedCreditBalance: `${counts[0]} credits`,
|
|
52331
|
+
...typeof row.plan === "string" ? { plan: row.plan } : {},
|
|
52332
|
+
...typeof row.hasPaymentMethod === "boolean" ? { hasPaymentMethod: row.hasPaymentMethod } : {}
|
|
52333
|
+
};
|
|
52334
|
+
}
|
|
52335
|
+
function parseRemoteCheckout(value) {
|
|
52336
|
+
const row = object(value);
|
|
52337
|
+
if (typeof row.url !== "string")
|
|
52338
|
+
throw new Error("Invalid checkout URL");
|
|
52339
|
+
const url = new URL(row.url);
|
|
52340
|
+
if (url.protocol !== "https:" || url.username || url.password)
|
|
52341
|
+
throw new Error("Invalid checkout URL");
|
|
52342
|
+
return { url: row.url };
|
|
52343
|
+
}
|
|
52344
|
+
function object(value) {
|
|
52345
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
52346
|
+
throw new Error("Invalid Skills server response");
|
|
52347
|
+
return value;
|
|
52348
|
+
}
|
|
52349
|
+
|
|
52350
|
+
// src/lib/remote-files.ts
|
|
52351
|
+
import { createHash as createHash13 } from "crypto";
|
|
52352
|
+
var MAX_REMOTE_FILE_BYTES = 64 * 1024 * 1024;
|
|
52353
|
+
function describeRemoteFiles(files) {
|
|
52354
|
+
if (files.length > 10)
|
|
52355
|
+
throw new Error("At most 10 input files are supported");
|
|
52356
|
+
const names = new Set;
|
|
52357
|
+
let total = 0;
|
|
52358
|
+
return files.map((file) => {
|
|
52359
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/.test(file.name) || file.name === "." || file.name === ".." || names.has(file.name))
|
|
52360
|
+
throw new Error("Input file names must be unique safe basenames");
|
|
52361
|
+
names.add(file.name);
|
|
52362
|
+
total += file.bytes.byteLength;
|
|
52363
|
+
if (file.bytes.byteLength > 20 * 1024 * 1024 || total > 50 * 1024 * 1024)
|
|
52364
|
+
throw new Error("Input files exceed the supported size limit");
|
|
52365
|
+
return { name: file.name, sizeBytes: file.bytes.byteLength, sha256: sha256(file.bytes), contentType: file.contentType ?? "application/octet-stream" };
|
|
52366
|
+
});
|
|
52367
|
+
}
|
|
52368
|
+
function sha256(bytes) {
|
|
52369
|
+
return createHash13("sha256").update(bytes).digest("hex");
|
|
52370
|
+
}
|
|
52371
|
+
async function readBoundedResponse(response, maximum) {
|
|
52372
|
+
if (!Number.isSafeInteger(maximum) || maximum < 0 || maximum > MAX_REMOTE_FILE_BYTES)
|
|
52373
|
+
throw new Error("Invalid artifact size limit");
|
|
52374
|
+
const length = response.headers.get("content-length");
|
|
52375
|
+
if (length && (!/^\d+$/.test(length) || Number(length) > maximum)) {
|
|
52376
|
+
await response.body?.cancel();
|
|
52377
|
+
throw new Error("Artifact exceeds its declared size limit");
|
|
52378
|
+
}
|
|
52379
|
+
const reader = response.body?.getReader();
|
|
52380
|
+
if (!reader)
|
|
52381
|
+
return new Uint8Array;
|
|
52382
|
+
const chunks = [];
|
|
52383
|
+
let size = 0;
|
|
52384
|
+
try {
|
|
52385
|
+
while (true) {
|
|
52386
|
+
const next = await reader.read();
|
|
52387
|
+
if (next.done)
|
|
52388
|
+
break;
|
|
52389
|
+
size += next.value.byteLength;
|
|
52390
|
+
if (size > maximum)
|
|
52391
|
+
throw new Error("Artifact exceeds its declared size limit");
|
|
52392
|
+
chunks.push(next.value);
|
|
52393
|
+
}
|
|
52394
|
+
} catch (error) {
|
|
52395
|
+
await reader.cancel().catch(() => {});
|
|
52396
|
+
throw error;
|
|
52397
|
+
} finally {
|
|
52398
|
+
reader.releaseLock();
|
|
52399
|
+
}
|
|
52400
|
+
const bytes = new Uint8Array(size);
|
|
52401
|
+
let offset = 0;
|
|
52402
|
+
for (const chunk of chunks) {
|
|
52403
|
+
bytes.set(chunk, offset);
|
|
52404
|
+
offset += chunk.byteLength;
|
|
52405
|
+
}
|
|
52406
|
+
return bytes;
|
|
52407
|
+
}
|
|
52408
|
+
|
|
52409
|
+
// src/lib/remote-profile.ts
|
|
52410
|
+
function customerNamePatch(input, field) {
|
|
52411
|
+
if (!isRecord5(input) || Object.keys(input).length !== 1 || !Object.hasOwn(input, field))
|
|
52412
|
+
throw new Error("Provide only the requested name field.");
|
|
52413
|
+
const value = input[field];
|
|
52414
|
+
if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
|
|
52415
|
+
throw new Error("Use a name of 1\u2013100 characters without control characters or newlines.");
|
|
52416
|
+
}
|
|
52417
|
+
return { [field]: value.trim() };
|
|
52418
|
+
}
|
|
52419
|
+
function isRecord5(value) {
|
|
52420
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
52421
|
+
}
|
|
52422
|
+
function string(value) {
|
|
52423
|
+
return typeof value === "string" && value.length > 0;
|
|
52424
|
+
}
|
|
52425
|
+
function parseUpdatedProfile(value) {
|
|
52426
|
+
const user = isRecord5(value) && value.user;
|
|
52427
|
+
if (!isRecord5(user) || !string(user.id) || !string(user.email) || !(user.displayName === null || typeof user.displayName === "string") || typeof user.role !== "string" || !["owner", "admin", "member", "viewer"].includes(user.role)) {
|
|
52428
|
+
throw new Error("The server returned an invalid account profile.");
|
|
52429
|
+
}
|
|
52430
|
+
return { user: { id: user.id, email: user.email, displayName: user.displayName, role: user.role } };
|
|
52431
|
+
}
|
|
52432
|
+
function parseUpdatedWorkspace(value) {
|
|
52433
|
+
const organization = isRecord5(value) && value.organization;
|
|
52434
|
+
if (!isRecord5(organization) || !string(organization.id) || !string(organization.slug) || !string(organization.name)) {
|
|
52435
|
+
throw new Error("The server returned an invalid workspace.");
|
|
52436
|
+
}
|
|
52437
|
+
return { organization: { id: organization.id, slug: organization.slug, name: organization.name } };
|
|
52438
|
+
}
|
|
52439
|
+
|
|
52440
|
+
// src/lib/remote-client.ts
|
|
52441
|
+
class RemoteRouteUnsupportedError extends Error {
|
|
52442
|
+
path;
|
|
52443
|
+
status;
|
|
52444
|
+
instance;
|
|
52445
|
+
constructor(path, status, instance) {
|
|
52446
|
+
super(`The configured Skills instance does not support ${path} (HTTP ${status}). ` + `The instance at ${instance} predates this client feature \u2014 upgrade the server, or ` + `use a client version that matches it.`);
|
|
52447
|
+
this.path = path;
|
|
52448
|
+
this.status = status;
|
|
52449
|
+
this.instance = instance;
|
|
52450
|
+
this.name = "RemoteRouteUnsupportedError";
|
|
52451
|
+
}
|
|
52452
|
+
}
|
|
52453
|
+
|
|
52454
|
+
class RemoteRequestError extends Error {
|
|
52455
|
+
path;
|
|
52456
|
+
status;
|
|
52457
|
+
constructor(path, status, _statusText) {
|
|
52458
|
+
super(`Remote request to ${path} failed: HTTP ${status}`);
|
|
52459
|
+
this.path = path;
|
|
52460
|
+
this.status = status;
|
|
52461
|
+
this.name = "RemoteRequestError";
|
|
52462
|
+
}
|
|
52463
|
+
}
|
|
52464
|
+
|
|
52465
|
+
class RemoteWorkspaceMemberError extends RemoteRequestError {
|
|
52466
|
+
code;
|
|
52467
|
+
constructor(path, code) {
|
|
52468
|
+
super(path, workspaceMemberFailures[code][0]);
|
|
52469
|
+
this.code = code;
|
|
52470
|
+
this.name = "RemoteWorkspaceMemberError";
|
|
52471
|
+
this.message = workspaceMemberFailures[code][1];
|
|
52472
|
+
}
|
|
52473
|
+
}
|
|
52474
|
+
|
|
52475
|
+
class RemoteCapabilityUnavailableError extends RemoteRequestError {
|
|
52476
|
+
code = "SUBSCRIPTION_CHECKOUT_UNAVAILABLE";
|
|
52477
|
+
constructor() {
|
|
52478
|
+
super("/api/v1/billing/checkout", 503);
|
|
52479
|
+
this.name = "RemoteCapabilityUnavailableError";
|
|
52480
|
+
this.message = "Subscription checkout is unavailable on the configured Skills server. " + "Use skills credits packs to view credit packs, or skills billing portal to manage an existing subscription.";
|
|
52481
|
+
}
|
|
52482
|
+
}
|
|
52483
|
+
|
|
52484
|
+
class RemoteSkillsClient {
|
|
52485
|
+
apiUrl;
|
|
52486
|
+
apiKey;
|
|
52487
|
+
capabilities;
|
|
52488
|
+
constructor(apiKey, apiUrl = getApiUrl()) {
|
|
52489
|
+
this.apiKey = apiKey;
|
|
52490
|
+
this.apiUrl = normalizeSkillsApiOrigin(apiUrl);
|
|
52491
|
+
}
|
|
52492
|
+
async request(path, options) {
|
|
52493
|
+
return fetch(`${this.apiUrl}${path}`, {
|
|
52494
|
+
...options,
|
|
52495
|
+
redirect: "error",
|
|
52496
|
+
signal: options?.signal ?? AbortSignal.timeout(15000),
|
|
52497
|
+
headers: {
|
|
52498
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
52499
|
+
"Content-Type": "application/json",
|
|
52500
|
+
...options?.headers
|
|
52501
|
+
}
|
|
52502
|
+
});
|
|
52503
|
+
}
|
|
52504
|
+
async requestNewRoute(path, options, opts = {}) {
|
|
52505
|
+
const response = await this.request(path, options);
|
|
52506
|
+
const routePath = path.split("?")[0];
|
|
52507
|
+
if (response.status === 404 || response.status === 405) {
|
|
52508
|
+
if (response.status === 404 && opts.domainNotFoundCodes?.length && await responseBodyCarriesCode(response, opts.domainNotFoundCodes)) {
|
|
52509
|
+
return response;
|
|
52510
|
+
}
|
|
52511
|
+
response.body?.cancel().catch(() => {});
|
|
52512
|
+
throw new RemoteRouteUnsupportedError(routePath, response.status, this.apiUrl);
|
|
52513
|
+
}
|
|
52514
|
+
if (!response.ok) {
|
|
52515
|
+
if (path === "/api/v1/billing/checkout" && options?.method === "POST" && response.status === 503 && await responseBodyCarriesCode(response, ["SUBSCRIPTION_CHECKOUT_UNAVAILABLE"])) {
|
|
52516
|
+
throw new RemoteCapabilityUnavailableError;
|
|
52517
|
+
}
|
|
52518
|
+
response.body?.cancel().catch(() => {});
|
|
52519
|
+
throw new RemoteRequestError(routePath, response.status, response.statusText);
|
|
52520
|
+
}
|
|
52521
|
+
return response;
|
|
52522
|
+
}
|
|
52523
|
+
async listSkills() {
|
|
52524
|
+
return this.arrayResponse("/api/v1/skills");
|
|
52525
|
+
}
|
|
52526
|
+
async getSkillMd(slug) {
|
|
52527
|
+
const res = await this.request(`/api/v1/skills/${slug}/skill.md`);
|
|
52528
|
+
if (!res.ok)
|
|
52529
|
+
return null;
|
|
52530
|
+
return res.text();
|
|
52531
|
+
}
|
|
52532
|
+
async getSkill(slug) {
|
|
52533
|
+
const res = await this.request(`/api/v1/skills/${slug}`);
|
|
52534
|
+
if (!res.ok)
|
|
52535
|
+
return null;
|
|
52536
|
+
return res.json();
|
|
52537
|
+
}
|
|
52538
|
+
async getSkillStatus(slug) {
|
|
52539
|
+
const res = await this.request(`/api/v1/skills/${encodeURIComponent(slug)}`, { method: "GET" });
|
|
52540
|
+
let body = null;
|
|
52541
|
+
try {
|
|
52542
|
+
body = await res.json();
|
|
52543
|
+
} catch {}
|
|
52544
|
+
return { status: res.status, body };
|
|
52545
|
+
}
|
|
52546
|
+
async submitRun(slug, input, args, approval = {}) {
|
|
52547
|
+
if (approval.idempotencyKey !== undefined && !/^[A-Za-z0-9._:-]{1,128}$/.test(approval.idempotencyKey))
|
|
52548
|
+
throw new Error("Idempotency key must be 1-128 URL-safe characters");
|
|
52549
|
+
if (approval.maxCostCents !== undefined)
|
|
52550
|
+
creditCount(approval.maxCostCents);
|
|
52551
|
+
if (approval.maxCredits !== undefined)
|
|
52552
|
+
creditCount(approval.maxCredits);
|
|
52553
|
+
if (approval.maxCredits !== undefined && approval.maxCostCents !== undefined && approval.maxCredits !== approval.maxCostCents)
|
|
52554
|
+
throw new Error("Credit approval fields disagree");
|
|
52555
|
+
const res = await this.request(`/api/v1/runs/${encodeURIComponent(slug)}`, {
|
|
52556
|
+
method: "POST",
|
|
52557
|
+
body: JSON.stringify({
|
|
52558
|
+
input,
|
|
52559
|
+
args,
|
|
52560
|
+
...approval.maxCredits !== undefined ? { maxCredits: approval.maxCredits } : {},
|
|
52561
|
+
...approval.maxCostCents !== undefined ? { maxCostCents: approval.maxCostCents } : {},
|
|
52562
|
+
...approval.idempotencyKey !== undefined ? { idempotencyKey: approval.idempotencyKey } : {},
|
|
52563
|
+
...approval.inputFiles !== undefined ? { files: approval.inputFiles } : {}
|
|
52564
|
+
})
|
|
52565
|
+
});
|
|
52566
|
+
return normalizeRemoteSkillRunContract(await res.json(), slug);
|
|
52567
|
+
}
|
|
52568
|
+
async quoteRun(slug, input = {}, args = []) {
|
|
52569
|
+
const response = await this.requestNewRoute(`/api/v1/skills/${encodeURIComponent(slug)}/quote`, {
|
|
52570
|
+
method: "POST",
|
|
52571
|
+
body: JSON.stringify({ input, args })
|
|
52572
|
+
});
|
|
52573
|
+
return parseRemoteRunQuote(await response.json());
|
|
52574
|
+
}
|
|
52575
|
+
getCapabilities() {
|
|
52576
|
+
if (!this.capabilities)
|
|
52577
|
+
this.capabilities = (async () => {
|
|
52578
|
+
const value = await (await this.requestNewRoute("/api/v1/capabilities")).json();
|
|
52579
|
+
if (value.contractVersion !== 1 || value.apiVersion !== 1 || !Array.isArray(value.capabilities) || value.capabilities.some((item) => typeof item !== "string"))
|
|
52580
|
+
throw new Error("Unsupported Skills server capability contract");
|
|
52581
|
+
const billing = value.billing;
|
|
52582
|
+
return { contractVersion: 1, apiVersion: 1, capabilities: value.capabilities, ...billing ? { billing } : {} };
|
|
52583
|
+
})();
|
|
52584
|
+
return this.capabilities;
|
|
52585
|
+
}
|
|
52586
|
+
async submitQuotedRun(slug, input = {}, args = [], approval = {}) {
|
|
52587
|
+
const maximum = creditCount(approval.maxCredits ?? approval.maxCostCents ?? 0);
|
|
52588
|
+
if (approval.maxCostCents !== undefined && approval.maxCostCents !== maximum)
|
|
52589
|
+
throw new Error("Credit approval fields disagree");
|
|
52590
|
+
const quote = await this.quoteRun(slug, input, args);
|
|
52591
|
+
if (quote.pricing.costCents > maximum)
|
|
52592
|
+
throw new RemoteCreditApprovalError(quote.pricing.costCents, maximum);
|
|
52593
|
+
const capabilities = await this.getCapabilities();
|
|
52594
|
+
if (!capabilities.capabilities.includes("runs.submit") || capabilities.billing?.boundedRunApproval !== true || capabilities.billing.unit !== "credits") {
|
|
52595
|
+
throw new Error("The configured server does not support bounded credit approval; refusing remote submission");
|
|
52596
|
+
}
|
|
52597
|
+
return this.submitRun(quote.skill, input, args, { ...approval, maxCredits: maximum, maxCostCents: maximum });
|
|
52598
|
+
}
|
|
52599
|
+
async getIdentity() {
|
|
52600
|
+
return (await this.requestNewRoute("/api/auth/whoami")).json();
|
|
52601
|
+
}
|
|
52602
|
+
async updateProfile(input) {
|
|
52603
|
+
const body = customerNamePatch(input, "displayName");
|
|
52604
|
+
return parseUpdatedProfile(await (await this.requestNewRoute("/api/v1/account/profile", { method: "PATCH", body: JSON.stringify(body) })).json());
|
|
52605
|
+
}
|
|
52606
|
+
async updateCurrentWorkspace(input) {
|
|
52607
|
+
const body = customerNamePatch(input, "name");
|
|
52608
|
+
return parseUpdatedWorkspace(await (await this.requestNewRoute("/api/v1/workspaces/current", { method: "PATCH", body: JSON.stringify(body) })).json());
|
|
52609
|
+
}
|
|
52610
|
+
async listWorkspaceMembers(options = {}) {
|
|
52611
|
+
const query = workspaceMembersQuery(options);
|
|
52612
|
+
const requestedCursor = options.cursor;
|
|
52613
|
+
const response = await this.requestNewRoute(`/api/v1/workspace/members${query}`);
|
|
52614
|
+
let value;
|
|
52615
|
+
try {
|
|
52616
|
+
value = await response.json();
|
|
52617
|
+
} catch {
|
|
52618
|
+
throw new Error("The server returned an invalid workspace roster.");
|
|
52619
|
+
}
|
|
52620
|
+
const page = parseWorkspaceMembersPage(value);
|
|
52621
|
+
if (requestedCursor !== undefined && page.nextCursor === requestedCursor)
|
|
52622
|
+
throw new Error("The server returned an invalid workspace roster.");
|
|
52623
|
+
return page;
|
|
52624
|
+
}
|
|
52625
|
+
async setWorkspaceMemberRole(membershipId, input) {
|
|
52626
|
+
const captured = workspaceMemberRoleInput(membershipId, input);
|
|
52627
|
+
const value = await this.requestWorkspaceMember(captured.membershipId, "PATCH", captured.body);
|
|
52628
|
+
return parseWorkspaceMemberRoleResult(value, captured.membershipId, captured.body.role);
|
|
52629
|
+
}
|
|
52630
|
+
async removeWorkspaceMember(membershipId, input) {
|
|
52631
|
+
const captured = workspaceMemberRemovalInput(membershipId, input);
|
|
52632
|
+
return parseWorkspaceMemberRemovalResult(await this.requestWorkspaceMember(captured.membershipId, "DELETE", captured.body), captured.membershipId);
|
|
52633
|
+
}
|
|
52634
|
+
async requestWorkspaceMember(membershipId, method, body) {
|
|
52635
|
+
const path = `/api/v1/workspace/members/${membershipId}`;
|
|
52636
|
+
const response = await this.request(path, { method, body: JSON.stringify(body) });
|
|
52637
|
+
let value;
|
|
52638
|
+
try {
|
|
52639
|
+
value = JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, response.ok ? 64 * 1024 : 4096)));
|
|
52640
|
+
} catch {
|
|
52641
|
+
if (response.ok)
|
|
52642
|
+
throw new Error(invalidMemberResult);
|
|
52643
|
+
}
|
|
52644
|
+
if (!response.ok) {
|
|
52645
|
+
const code = workspaceMemberFailure(value, response.status);
|
|
52646
|
+
if (code)
|
|
52647
|
+
throw new RemoteWorkspaceMemberError(path, code);
|
|
52648
|
+
if (response.status === 404 || response.status === 405)
|
|
52649
|
+
throw new RemoteRouteUnsupportedError(path, response.status, this.apiUrl);
|
|
52650
|
+
throw new RemoteRequestError(path, response.status);
|
|
52651
|
+
}
|
|
52652
|
+
return value;
|
|
52653
|
+
}
|
|
52654
|
+
async listApiKeys() {
|
|
52655
|
+
return this.arrayResponse("/api/auth/keys");
|
|
52656
|
+
}
|
|
52657
|
+
async createApiKey(name, scopes) {
|
|
52658
|
+
if (!name.trim() || name.length > 100)
|
|
52659
|
+
throw new Error("API key name must be 1-100 characters");
|
|
52660
|
+
const value = await (await this.requestNewRoute("/api/auth/keys", { method: "POST", body: JSON.stringify({ name, ...scopes ? { scopes } : {} }) })).json();
|
|
52661
|
+
if (!value || typeof value.key !== "string" || !value.key.trim())
|
|
52662
|
+
throw new Error("The server did not return a created API key");
|
|
52663
|
+
return value;
|
|
52664
|
+
}
|
|
52665
|
+
async revokeApiKey(keyId) {
|
|
52666
|
+
return (await this.requestNewRoute(`/api/auth/keys/${encodeURIComponent(keyId)}`, { method: "DELETE" })).json();
|
|
52667
|
+
}
|
|
52668
|
+
async getBillingStatus() {
|
|
52669
|
+
return parseRemoteBillingStatus(await (await this.requestNewRoute("/api/v1/billing/status")).json());
|
|
52670
|
+
}
|
|
52671
|
+
async listCreditPacks() {
|
|
52672
|
+
return parseRemoteCreditPacks(await (await this.requestNewRoute("/api/v1/billing/credits")).json());
|
|
52673
|
+
}
|
|
52674
|
+
async createCreditCheckout(packId) {
|
|
52675
|
+
const packs = await this.listCreditPacks();
|
|
52676
|
+
if (!packs.some((pack) => pack.id === packId))
|
|
52677
|
+
throw new Error("Choose a credit pack returned by skills credits packs");
|
|
52678
|
+
return parseRemoteCheckout(await (await this.requestNewRoute("/api/v1/billing/credits", {
|
|
52679
|
+
method: "POST",
|
|
52680
|
+
body: JSON.stringify({ packId })
|
|
52681
|
+
})).json());
|
|
52682
|
+
}
|
|
52683
|
+
async getUsage() {
|
|
52684
|
+
return this.arrayResponse("/api/v1/billing/usage");
|
|
52685
|
+
}
|
|
52686
|
+
async listInvoices() {
|
|
52687
|
+
return this.arrayResponse("/api/v1/billing/invoices");
|
|
52688
|
+
}
|
|
52689
|
+
async createBillingCheckout() {
|
|
52690
|
+
return this.checkoutResponse("/api/v1/billing/checkout");
|
|
52691
|
+
}
|
|
52692
|
+
async createBillingPortal() {
|
|
52693
|
+
return this.checkoutResponse("/api/v1/billing/portal");
|
|
52694
|
+
}
|
|
52695
|
+
async cancelRun(runId2) {
|
|
52696
|
+
return this.controlRun(runId2, "cancel");
|
|
52697
|
+
}
|
|
52698
|
+
async resumeRun(runId2) {
|
|
52699
|
+
return this.controlRun(runId2, "resume");
|
|
52700
|
+
}
|
|
52701
|
+
async controlRun(runId2, action) {
|
|
52702
|
+
const response = await this.requestNewRoute(`/api/v1/runs/${encodeURIComponent(runId2)}/${action}`, { method: "POST", body: "{}" });
|
|
52703
|
+
return normalizeRemoteSkillRunContract(await response.json());
|
|
52704
|
+
}
|
|
52705
|
+
async checkoutResponse(path) {
|
|
52706
|
+
return parseRemoteCheckout(await (await this.requestNewRoute(path, { method: "POST", body: "{}" })).json());
|
|
52707
|
+
}
|
|
52708
|
+
async arrayResponse(path) {
|
|
52709
|
+
const rows = await (await this.requestNewRoute(path)).json();
|
|
52710
|
+
if (!Array.isArray(rows) || rows.some((row) => !row || typeof row !== "object" || Array.isArray(row)))
|
|
52711
|
+
throw new Error("Invalid Skills server list response");
|
|
52712
|
+
return rows;
|
|
52713
|
+
}
|
|
52714
|
+
async getRun(runId2) {
|
|
52715
|
+
const path = `/api/v1/runs/${encodeURIComponent(runId2)}`;
|
|
52716
|
+
const res = await this.request(path);
|
|
52717
|
+
if (res.status === 404)
|
|
52718
|
+
return null;
|
|
52719
|
+
if (!res.ok)
|
|
52720
|
+
throw new RemoteRequestError(path, res.status, res.statusText);
|
|
52721
|
+
return normalizeRemoteSkillRunContract(await res.json());
|
|
52722
|
+
}
|
|
52723
|
+
async getRunLogs(runId2) {
|
|
52724
|
+
return this.arrayResponse(`/api/v1/runs/${encodeURIComponent(runId2)}/logs`);
|
|
52725
|
+
}
|
|
52726
|
+
async listRuns(limit = 20) {
|
|
52727
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
52728
|
+
throw new Error("Run limit must be an integer from 1 to 100");
|
|
52729
|
+
return this.arrayResponse(`/api/v1/runs?limit=${limit}`);
|
|
52730
|
+
}
|
|
52731
|
+
async getRunArtifacts(runId2) {
|
|
52732
|
+
return this.arrayResponse(`/api/v1/runs/${encodeURIComponent(runId2)}/artifacts`);
|
|
52733
|
+
}
|
|
52734
|
+
async downloadRunArtifact(runId2, artifactId2) {
|
|
52735
|
+
return this.request(`/api/v1/runs/${encodeURIComponent(runId2)}/artifacts/${encodeURIComponent(artifactId2)}/download`, {
|
|
52736
|
+
method: "GET"
|
|
52737
|
+
});
|
|
52738
|
+
}
|
|
52739
|
+
async getVerifiedRunArtifact(runId2, artifactId2, maximumBytes = MAX_REMOTE_FILE_BYTES) {
|
|
52740
|
+
const artifacts = await this.getRunArtifacts(runId2);
|
|
52741
|
+
const artifact = artifacts.find((row) => row.id === artifactId2);
|
|
52742
|
+
if (!artifact)
|
|
52743
|
+
throw new Error("Run artifact not found");
|
|
52744
|
+
if (!Number.isSafeInteger(artifact.byteSize) || artifact.byteSize < 0 || artifact.byteSize > maximumBytes || typeof artifact.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(artifact.sha256))
|
|
52745
|
+
throw new Error("The server does not provide valid artifact integrity metadata");
|
|
52746
|
+
const response = await this.downloadRunArtifact(runId2, artifactId2);
|
|
52747
|
+
if (!response.ok)
|
|
52748
|
+
throw new RemoteRequestError("artifact download", response.status, response.statusText);
|
|
52749
|
+
const bytes = await readBoundedResponse(response, artifact.byteSize);
|
|
52750
|
+
if (bytes.byteLength !== artifact.byteSize || sha256(bytes) !== artifact.sha256)
|
|
52751
|
+
throw new Error("Artifact integrity verification failed");
|
|
52752
|
+
return { id: artifactId2, fileName: String(artifact.fileName ?? artifactId2), bytes, byteSize: bytes.byteLength, sha256: artifact.sha256 };
|
|
52753
|
+
}
|
|
52754
|
+
async submitQuotedRunWithFiles(slug, input, args, files, approval = {}) {
|
|
52755
|
+
const inputFiles = describeRemoteFiles(files);
|
|
52756
|
+
if (files.length && !(await this.getCapabilities()).capabilities.includes("runs.uploads"))
|
|
52757
|
+
throw new Error("The configured server does not support input uploads");
|
|
52758
|
+
const run = await this.submitQuotedRun(slug, input, args, { ...approval, inputFiles });
|
|
52759
|
+
if (run.error || !run.id || !files.length)
|
|
52760
|
+
return run;
|
|
52761
|
+
const pastUploads = (status) => typeof status === "string" && [
|
|
52762
|
+
"running",
|
|
52763
|
+
"completed",
|
|
52764
|
+
"failed",
|
|
52765
|
+
"cancelled",
|
|
52766
|
+
"expired",
|
|
52767
|
+
"pending_approval",
|
|
52768
|
+
"approved",
|
|
52769
|
+
"waiting"
|
|
52770
|
+
].includes(status);
|
|
52771
|
+
if (pastUploads(run.status))
|
|
52772
|
+
return run;
|
|
52773
|
+
try {
|
|
52774
|
+
await this.uploadRunFiles(run.id, files);
|
|
52775
|
+
} catch {
|
|
52776
|
+
try {
|
|
52777
|
+
const current = await this.getRun(run.id);
|
|
52778
|
+
if (current && pastUploads(current.status))
|
|
52779
|
+
return current;
|
|
52780
|
+
} catch {}
|
|
52781
|
+
let cancellationRequested = false;
|
|
52782
|
+
try {
|
|
52783
|
+
await this.cancelRun(run.id);
|
|
52784
|
+
cancellationRequested = true;
|
|
52785
|
+
} catch {}
|
|
52786
|
+
throw new Error(`Input upload failed for run ${run.id}; ${cancellationRequested ? "cancellation requested" : "check its status and cancel the run"}`);
|
|
52787
|
+
}
|
|
52788
|
+
return run;
|
|
52789
|
+
}
|
|
52790
|
+
async uploadRunFiles(runId2, files) {
|
|
52791
|
+
const descriptors = describeRemoteFiles(files);
|
|
52792
|
+
const response = await this.requestNewRoute(`/api/v1/runs/${encodeURIComponent(runId2)}/uploads`, { method: "POST", body: JSON.stringify({ files: descriptors }) });
|
|
52793
|
+
const payload = await response.json();
|
|
52794
|
+
if (!Array.isArray(payload.files) || payload.files.length !== files.length || new Set(payload.files.map((file) => file.name)).size !== files.length)
|
|
52795
|
+
throw new Error("Invalid input upload response");
|
|
52796
|
+
for (const file of files) {
|
|
52797
|
+
const upload = payload.files.find((row) => row.name === file.name);
|
|
52798
|
+
if (!upload)
|
|
52799
|
+
throw new Error("Missing input upload URL");
|
|
52800
|
+
const url = new URL(upload.uploadUrl);
|
|
52801
|
+
if (url.username || url.password || url.hash || url.protocol !== "https:" && !(url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname)))
|
|
52802
|
+
throw new Error("Unsafe input upload URL");
|
|
52803
|
+
const uploaded = await fetch(url, { method: "PUT", body: file.bytes, headers: { "Content-Type": file.contentType ?? "application/octet-stream" }, redirect: "error", signal: AbortSignal.timeout(60000) });
|
|
52804
|
+
if (!uploaded.ok)
|
|
52805
|
+
throw new Error("Input upload failed");
|
|
52806
|
+
await uploaded.body?.cancel();
|
|
52807
|
+
}
|
|
52808
|
+
}
|
|
52809
|
+
async publishSkill(manifest, bundle, ifMatch) {
|
|
52810
|
+
const form = new FormData;
|
|
52811
|
+
form.set("manifest", JSON.stringify(manifest));
|
|
52812
|
+
if (bundle) {
|
|
52813
|
+
form.set("bundle", new Blob([bundle], { type: "application/gzip" }), `${String(manifest.slug ?? "skill")}.tar.gz`);
|
|
52814
|
+
}
|
|
52815
|
+
const headers = { Authorization: `Bearer ${this.apiKey}` };
|
|
52816
|
+
if (ifMatch)
|
|
52817
|
+
headers["If-Match"] = ifMatch;
|
|
52818
|
+
return fetch(`${this.apiUrl}/api/v1/skills`, {
|
|
52819
|
+
method: "POST",
|
|
52820
|
+
headers,
|
|
52821
|
+
body: form,
|
|
52822
|
+
redirect: "error",
|
|
52823
|
+
signal: AbortSignal.timeout(15000)
|
|
52824
|
+
});
|
|
52825
|
+
}
|
|
52826
|
+
async deleteSkill(slug) {
|
|
52827
|
+
return this.request(`/api/v1/skills/${encodeURIComponent(slug)}`, { method: "DELETE" });
|
|
52828
|
+
}
|
|
52829
|
+
async downloadSkillBundle(slug) {
|
|
52830
|
+
return this.request(`/api/v1/skills/${encodeURIComponent(slug)}/bundle`, { method: "GET" });
|
|
52831
|
+
}
|
|
52832
|
+
async getBundle(slug, version2) {
|
|
52833
|
+
const path = version2 ? `/api/v1/skills/${encodeURIComponent(slug)}/versions/${encodeURIComponent(version2)}/bundle` : `/api/v1/skills/${encodeURIComponent(slug)}/bundle`;
|
|
52834
|
+
const response = await this.request(path, { method: "GET" });
|
|
52835
|
+
if (response.status === 404)
|
|
52836
|
+
return null;
|
|
52837
|
+
return response;
|
|
52838
|
+
}
|
|
52839
|
+
async listSkillVersions(slug) {
|
|
52840
|
+
const response = await this.requestNewRoute(`/api/v1/skills/${encodeURIComponent(slug)}/versions`, undefined, { domainNotFoundCodes: ["SKILL_NOT_FOUND"] });
|
|
52841
|
+
if (response.status === 404)
|
|
52842
|
+
return [];
|
|
52843
|
+
if (!response.ok)
|
|
52844
|
+
throw new Error(`versions request failed: ${response.status}`);
|
|
52845
|
+
const body = await readSkillVersionPayload(response);
|
|
52846
|
+
if (!isVersionRecord(body) || !Array.isArray(body.versions) || body.slug !== undefined && body.slug !== slug)
|
|
52847
|
+
throw new Error(INVALID_SKILL_VERSION_RESPONSE);
|
|
52848
|
+
return body.versions.map((entry) => normalizeSkillVersion(entry, slug));
|
|
52849
|
+
}
|
|
52850
|
+
async getSkillVersion(slug, version2) {
|
|
52851
|
+
const response = await this.requestNewRoute(`/api/v1/skills/${encodeURIComponent(slug)}/versions/${encodeURIComponent(version2)}`, undefined, { domainNotFoundCodes: ["SKILL_NOT_FOUND", "SKILL_VERSION_NOT_FOUND"] });
|
|
52852
|
+
if (response.status === 404)
|
|
52853
|
+
return null;
|
|
52854
|
+
if (!response.ok)
|
|
52855
|
+
throw new Error(`version request failed: ${response.status}`);
|
|
52856
|
+
return normalizeSkillVersion(await readSkillVersionPayload(response), slug, version2);
|
|
52857
|
+
}
|
|
52858
|
+
async listPins() {
|
|
52859
|
+
const response = await this.requestNewRoute("/api/v1/pins");
|
|
52860
|
+
return normalizePinList(await response.json());
|
|
52861
|
+
}
|
|
52862
|
+
async pin(slug, metadata) {
|
|
52863
|
+
const path = `/api/v1/pins/${encodeURIComponent(slug)}`;
|
|
52864
|
+
const response = await this.requestNewRoute(path, {
|
|
52865
|
+
method: "PUT",
|
|
52866
|
+
body: JSON.stringify({ ...metadata ? { metadata } : {} })
|
|
52867
|
+
});
|
|
52868
|
+
return normalizePin(await response.json());
|
|
52869
|
+
}
|
|
52870
|
+
async unpin(slug) {
|
|
52871
|
+
const path = `/api/v1/pins/${encodeURIComponent(slug)}`;
|
|
52872
|
+
const response = await this.requestNewRoute(path, { method: "DELETE" }, { domainNotFoundCodes: ["PIN_NOT_FOUND"] });
|
|
52873
|
+
return response.status !== 404;
|
|
52874
|
+
}
|
|
52875
|
+
async listTags() {
|
|
52876
|
+
const response = await this.requestNewRoute("/api/v1/tags");
|
|
52877
|
+
const payload = await response.json();
|
|
52878
|
+
if (!Array.isArray(payload)) {
|
|
52879
|
+
throw new Error("Remote tags payload did not match the expected contract (expected an array of tag names)");
|
|
52880
|
+
}
|
|
52881
|
+
const isName = (value) => typeof value === "string" && value.trim().length > 0;
|
|
52882
|
+
if (payload.every(isName))
|
|
52883
|
+
return payload;
|
|
52884
|
+
if (payload.every((tag) => tag !== null && typeof tag === "object" && !Array.isArray(tag) && isName(tag.name) && Number.isSafeInteger(tag.count) && tag.count >= 0)) {
|
|
52885
|
+
return payload.map((tag) => tag.name);
|
|
52886
|
+
}
|
|
52887
|
+
throw new Error("Remote tags payload did not match the expected contract (every element must be a non-empty tag name, or every element must be a counted tag record)");
|
|
52888
|
+
}
|
|
52889
|
+
async skillsByTag(tag) {
|
|
52890
|
+
const path = `/api/v1/tags/${encodeURIComponent(tag)}/skills`;
|
|
52891
|
+
const response = await this.requestNewRoute(path);
|
|
52892
|
+
return normalizeSkillSummaryList(await response.json());
|
|
52893
|
+
}
|
|
52894
|
+
async listUpdatedSince(since, options = {}) {
|
|
52895
|
+
const params = new URLSearchParams({ since });
|
|
52896
|
+
if (options.cursor)
|
|
52897
|
+
params.set("cursor", options.cursor);
|
|
52898
|
+
if (options.limit !== undefined)
|
|
52899
|
+
params.set("limit", String(options.limit));
|
|
52900
|
+
const response = await this.requestNewRoute(`/api/v1/skills/updated?${params.toString()}`);
|
|
52901
|
+
return normalizeUpdatedSincePage(await response.json());
|
|
52902
|
+
}
|
|
52903
|
+
}
|
|
52904
|
+
function requireOptionalString(record2, field) {
|
|
52905
|
+
if (record2[field] === undefined)
|
|
52906
|
+
return;
|
|
52907
|
+
if (typeof record2[field] !== "string") {
|
|
52908
|
+
throw new Error(`Remote payload did not match the expected contract (${field} must be a string when present)`);
|
|
52909
|
+
}
|
|
52910
|
+
return record2[field];
|
|
52911
|
+
}
|
|
52912
|
+
var INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
52913
|
+
function isVersionRecord(value) {
|
|
52914
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
52915
|
+
}
|
|
52916
|
+
async function readSkillVersionPayload(response) {
|
|
52917
|
+
try {
|
|
52918
|
+
return await response.json();
|
|
52919
|
+
} catch {
|
|
52920
|
+
throw new Error(INVALID_SKILL_VERSION_RESPONSE);
|
|
52921
|
+
}
|
|
52922
|
+
}
|
|
52923
|
+
function normalizeSkillVersion(entry, slug, version2) {
|
|
52924
|
+
if (!isVersionRecord(entry) || typeof entry.slug !== "string" || !entry.slug.trim() || entry.slug !== slug || typeof entry.version !== "string" || !entry.version.trim() || version2 !== undefined && entry.version !== version2 || typeof entry.bundleSha256 !== "string" || !/^[a-f0-9]{64}$/i.test(entry.bundleSha256) || typeof entry.bundleByteSize !== "number" || !Number.isSafeInteger(entry.bundleByteSize) || entry.bundleByteSize < 0 || typeof entry.createdAt !== "string" || !entry.createdAt.trim() || entry.current !== undefined && typeof entry.current !== "boolean" || entry.storageKind !== undefined && typeof entry.storageKind !== "string" || entry.manifest !== undefined && !isVersionRecord(entry.manifest)) {
|
|
52925
|
+
throw new Error(INVALID_SKILL_VERSION_RESPONSE);
|
|
52926
|
+
}
|
|
52927
|
+
return entry;
|
|
52928
|
+
}
|
|
52929
|
+
function normalizePin(entry) {
|
|
52930
|
+
if (!entry || typeof entry !== "object") {
|
|
52931
|
+
throw new Error("Remote pin payload did not match the expected contract (expected an object)");
|
|
52932
|
+
}
|
|
52933
|
+
const record2 = entry;
|
|
52934
|
+
const slug = typeof record2.slug === "string" && record2.slug.trim() ? record2.slug.trim() : undefined;
|
|
52935
|
+
if (!slug) {
|
|
52936
|
+
throw new Error("Remote pin payload did not match the expected contract (missing slug)");
|
|
52937
|
+
}
|
|
52938
|
+
let metadata;
|
|
52939
|
+
if (record2.metadata !== undefined) {
|
|
52940
|
+
if (!record2.metadata || typeof record2.metadata !== "object" || Array.isArray(record2.metadata)) {
|
|
52941
|
+
throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
|
|
52942
|
+
}
|
|
52943
|
+
metadata = record2.metadata;
|
|
52944
|
+
}
|
|
52945
|
+
const pinnedAt = requireOptionalString(record2, "pinnedAt");
|
|
52946
|
+
return {
|
|
52947
|
+
slug,
|
|
52948
|
+
...pinnedAt !== undefined ? { pinnedAt } : {},
|
|
52949
|
+
...metadata ? { metadata } : {}
|
|
52950
|
+
};
|
|
52951
|
+
}
|
|
52952
|
+
function normalizePinList(payload) {
|
|
52953
|
+
if (!Array.isArray(payload)) {
|
|
52954
|
+
throw new Error("Remote pins payload did not match the expected contract (expected an array of pins)");
|
|
52955
|
+
}
|
|
52956
|
+
return payload.map(normalizePin);
|
|
52957
|
+
}
|
|
52958
|
+
function normalizeSkillSummary(entry) {
|
|
52959
|
+
if (!entry || typeof entry !== "object") {
|
|
52960
|
+
throw new Error("Remote skill payload did not match the expected contract (expected an object)");
|
|
52961
|
+
}
|
|
52962
|
+
const record2 = entry;
|
|
52963
|
+
const slug = typeof record2.slug === "string" && record2.slug.trim() ? record2.slug.trim() : undefined;
|
|
52964
|
+
if (!slug) {
|
|
52965
|
+
throw new Error("Remote skill payload did not match the expected contract (missing slug)");
|
|
52966
|
+
}
|
|
52967
|
+
return {
|
|
52968
|
+
slug,
|
|
52969
|
+
...requireOptionalString(record2, "name") !== undefined ? { name: requireOptionalString(record2, "name") } : {},
|
|
52970
|
+
...requireOptionalString(record2, "version") !== undefined ? { version: requireOptionalString(record2, "version") } : {},
|
|
52971
|
+
...requireOptionalString(record2, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record2, "updatedAt") } : {}
|
|
52972
|
+
};
|
|
52973
|
+
}
|
|
52974
|
+
function normalizeSkillSummaryList(payload) {
|
|
52975
|
+
if (!Array.isArray(payload)) {
|
|
52976
|
+
throw new Error("Remote skills payload did not match the expected contract (expected an array of skills)");
|
|
52977
|
+
}
|
|
52978
|
+
return payload.map(normalizeSkillSummary);
|
|
52979
|
+
}
|
|
52980
|
+
async function responseBodyCarriesCode(response, codes) {
|
|
52981
|
+
const reader = response.body?.getReader();
|
|
52982
|
+
if (!reader)
|
|
52983
|
+
return false;
|
|
52984
|
+
const maximum = 8 * 1024;
|
|
52985
|
+
let deadline;
|
|
52986
|
+
const expired = new Promise((_, reject) => {
|
|
52987
|
+
deadline = setTimeout(() => reject(new Error("Error response read deadline exceeded")), 1000);
|
|
52988
|
+
});
|
|
52989
|
+
try {
|
|
52990
|
+
const chunks = [];
|
|
52991
|
+
let size = 0;
|
|
52992
|
+
while (true) {
|
|
52993
|
+
const next = await Promise.race([reader.read(), expired]);
|
|
52994
|
+
if (next.done)
|
|
52995
|
+
break;
|
|
52996
|
+
size += next.value.byteLength;
|
|
52997
|
+
if (size > maximum)
|
|
52998
|
+
return false;
|
|
52999
|
+
chunks.push(next.value);
|
|
53000
|
+
}
|
|
53001
|
+
const bytes = new Uint8Array(size);
|
|
53002
|
+
let offset = 0;
|
|
53003
|
+
for (const chunk of chunks) {
|
|
53004
|
+
bytes.set(chunk, offset);
|
|
53005
|
+
offset += chunk.byteLength;
|
|
53006
|
+
}
|
|
53007
|
+
const payload = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
53008
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload) || !Object.hasOwn(payload, "code"))
|
|
53009
|
+
return false;
|
|
53010
|
+
const code = payload.code;
|
|
53011
|
+
return typeof code === "string" && codes.includes(code);
|
|
53012
|
+
} catch {
|
|
53013
|
+
return false;
|
|
53014
|
+
} finally {
|
|
53015
|
+
clearTimeout(deadline);
|
|
53016
|
+
reader.cancel().catch(() => {});
|
|
53017
|
+
reader.releaseLock();
|
|
53018
|
+
}
|
|
53019
|
+
}
|
|
53020
|
+
function normalizeUpdatedSincePage(payload) {
|
|
53021
|
+
if (!payload || typeof payload !== "object") {
|
|
53022
|
+
throw new Error("Updated-since payload did not match the expected contract (expected an object)");
|
|
53023
|
+
}
|
|
53024
|
+
const record2 = payload;
|
|
53025
|
+
if (!Array.isArray(record2.skills)) {
|
|
53026
|
+
throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
|
|
53027
|
+
}
|
|
53028
|
+
const skills = record2.skills.map(normalizeSkillSummary);
|
|
53029
|
+
const nextCursor = record2.nextCursor === undefined || record2.nextCursor === null ? null : record2.nextCursor;
|
|
53030
|
+
if (nextCursor !== null && typeof nextCursor !== "string") {
|
|
53031
|
+
throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
|
|
53032
|
+
}
|
|
53033
|
+
return { skills, nextCursor };
|
|
53034
|
+
}
|
|
53035
|
+
async function createRemoteSkillsClient(env = process.env) {
|
|
53036
|
+
const connection = await resolveSkillsConnection(env);
|
|
53037
|
+
return connection ? new RemoteSkillsClient(connection.apiKey, connection.apiOrigin) : null;
|
|
53038
|
+
}
|
|
53039
|
+
// src/lib/remote-auth.ts
|
|
53040
|
+
var MAX_ERROR_DETAIL_LENGTH = 200;
|
|
53041
|
+
|
|
53042
|
+
class HostedApiError extends Error {
|
|
53043
|
+
status;
|
|
53044
|
+
code;
|
|
53045
|
+
detail;
|
|
53046
|
+
endpoint;
|
|
53047
|
+
apiUrl;
|
|
53048
|
+
constructor(message, options = {}) {
|
|
53049
|
+
super(message);
|
|
53050
|
+
this.name = "HostedApiError";
|
|
53051
|
+
this.status = options.status;
|
|
53052
|
+
this.code = options.code;
|
|
53053
|
+
this.detail = options.detail;
|
|
53054
|
+
this.endpoint = options.endpoint;
|
|
53055
|
+
this.apiUrl = options.apiUrl;
|
|
53056
|
+
}
|
|
53057
|
+
}
|
|
53058
|
+
async function requestAuthApi(instance, path, options) {
|
|
53059
|
+
const url = normalizeSkillsApiOrigin(instance);
|
|
53060
|
+
const safeUrl = url;
|
|
53061
|
+
const endpoint = `${(options?.method || "GET").toUpperCase()} ${safeUrl}${path}`;
|
|
53062
|
+
let res;
|
|
53063
|
+
try {
|
|
53064
|
+
res = await fetch(`${url}${path}`, {
|
|
53065
|
+
...options,
|
|
53066
|
+
redirect: "error",
|
|
53067
|
+
signal: options?.signal ?? AbortSignal.timeout(15000),
|
|
53068
|
+
headers: { "Content-Type": "application/json", ...options?.headers }
|
|
53069
|
+
});
|
|
53070
|
+
} catch (err) {
|
|
53071
|
+
throw new HostedApiError(`Unable to reach the Skills API: ${err.message}`, {
|
|
53072
|
+
endpoint,
|
|
53073
|
+
apiUrl: safeUrl
|
|
53074
|
+
});
|
|
53075
|
+
}
|
|
53076
|
+
const text = await res.text();
|
|
53077
|
+
const body = text ? parseJsonBody(text) : {};
|
|
53078
|
+
if (!res.ok) {
|
|
53079
|
+
const record2 = isRecord6(body) ? body : {};
|
|
53080
|
+
const detail = typeof record2.detail === "string" ? record2.detail : undefined;
|
|
53081
|
+
const error = typeof record2.error === "string" ? record2.error : undefined;
|
|
53082
|
+
const code = typeof record2.code === "string" ? record2.code : undefined;
|
|
53083
|
+
throw new HostedApiError(detail || error || `${res.status} ${res.statusText}`, {
|
|
53084
|
+
status: res.status,
|
|
53085
|
+
code,
|
|
53086
|
+
detail,
|
|
53087
|
+
endpoint,
|
|
53088
|
+
apiUrl: safeUrl
|
|
53089
|
+
});
|
|
53090
|
+
}
|
|
53091
|
+
return body;
|
|
53092
|
+
}
|
|
53093
|
+
function parseJsonBody(text) {
|
|
53094
|
+
try {
|
|
53095
|
+
return JSON.parse(text);
|
|
53096
|
+
} catch {
|
|
53097
|
+
return { detail: condenseErrorBody(text) };
|
|
53098
|
+
}
|
|
53099
|
+
}
|
|
53100
|
+
function condenseErrorBody(text) {
|
|
53101
|
+
const stripped = /<[a-z!/]/i.test(text) ? text.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text;
|
|
53102
|
+
const collapsed = stripped.replace(/\s+/g, " ").trim();
|
|
53103
|
+
if (collapsed.length <= MAX_ERROR_DETAIL_LENGTH)
|
|
53104
|
+
return collapsed;
|
|
53105
|
+
return `${collapsed.slice(0, MAX_ERROR_DETAIL_LENGTH - 1).trimEnd()}\u2026`;
|
|
53106
|
+
}
|
|
53107
|
+
function isRecord6(value) {
|
|
53108
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
53109
|
+
}
|
|
53110
|
+
|
|
53111
|
+
class RemoteSkillsAuthClient {
|
|
53112
|
+
apiOrigin;
|
|
53113
|
+
constructor(apiUrl) {
|
|
53114
|
+
this.apiOrigin = normalizeSkillsApiOrigin(apiUrl);
|
|
53115
|
+
}
|
|
53116
|
+
requestCode(email) {
|
|
53117
|
+
return this.request("/api/auth/login", { method: "POST", body: JSON.stringify({ email }) });
|
|
53118
|
+
}
|
|
53119
|
+
verifyCode(email, code) {
|
|
53120
|
+
return this.request("/api/auth/verify", { method: "POST", body: JSON.stringify({ email, code }) });
|
|
53121
|
+
}
|
|
53122
|
+
startDevice() {
|
|
53123
|
+
return this.request("/api/auth/device/start", { method: "POST", body: JSON.stringify({ client: "skills-sdk" }) });
|
|
53124
|
+
}
|
|
53125
|
+
pollDevice(deviceCode) {
|
|
53126
|
+
return this.request("/api/auth/device/token", { method: "POST", body: JSON.stringify({ deviceCode }) });
|
|
53127
|
+
}
|
|
53128
|
+
async sessionClient(email, code) {
|
|
53129
|
+
const apiOrigin = this.apiOrigin;
|
|
53130
|
+
if (!email.includes("@") || !/^\d{6}$/.test(code))
|
|
53131
|
+
throw new Error("Fresh email and six-digit verification code are required to manage this account");
|
|
53132
|
+
const login = await this.verifyCode(email, code);
|
|
53133
|
+
if (!login || typeof login.token !== "string" || !login.token)
|
|
53134
|
+
throw new Error("The server did not return an authorized account session");
|
|
53135
|
+
return new RemoteSkillsClient(login.token, apiOrigin);
|
|
53136
|
+
}
|
|
53137
|
+
async createApiKey(email, code, name, scopes) {
|
|
53138
|
+
return (await this.sessionClient(email, code)).createApiKey(name, scopes);
|
|
53139
|
+
}
|
|
53140
|
+
async listApiKeys(email, code) {
|
|
53141
|
+
return (await this.sessionClient(email, code)).listApiKeys();
|
|
53142
|
+
}
|
|
53143
|
+
async revokeApiKey(email, code, keyId) {
|
|
53144
|
+
return (await this.sessionClient(email, code)).revokeApiKey(keyId);
|
|
53145
|
+
}
|
|
53146
|
+
async updateProfile(email, code, input) {
|
|
53147
|
+
customerNamePatch(input, "displayName");
|
|
53148
|
+
return (await this.sessionClient(email, code)).updateProfile(input);
|
|
53149
|
+
}
|
|
53150
|
+
async updateCurrentWorkspace(email, code, input) {
|
|
53151
|
+
customerNamePatch(input, "name");
|
|
53152
|
+
return (await this.sessionClient(email, code)).updateCurrentWorkspace(input);
|
|
53153
|
+
}
|
|
53154
|
+
async listWorkspaceMembers(email, code, options = {}) {
|
|
53155
|
+
workspaceMembersQuery(options);
|
|
53156
|
+
return (await this.sessionClient(email, code)).listWorkspaceMembers(options);
|
|
53157
|
+
}
|
|
53158
|
+
async setWorkspaceMemberRole(email, code, membershipId, input) {
|
|
53159
|
+
const captured = workspaceMemberRoleInput(membershipId, input);
|
|
53160
|
+
return (await this.sessionClient(email, code)).setWorkspaceMemberRole(captured.membershipId, captured.body);
|
|
53161
|
+
}
|
|
53162
|
+
async removeWorkspaceMember(email, code, membershipId, input) {
|
|
53163
|
+
const captured = workspaceMemberRemovalInput(membershipId, input);
|
|
53164
|
+
return (await this.sessionClient(email, code)).removeWorkspaceMember(captured.membershipId, captured.body);
|
|
53165
|
+
}
|
|
53166
|
+
request(path, options) {
|
|
53167
|
+
if (!["/api/auth/login", "/api/auth/verify", "/api/auth/device/start", "/api/auth/device/token", "/api/auth/keys", "/api/auth/whoami"].includes(path))
|
|
53168
|
+
throw new Error("Unsupported authentication operation");
|
|
53169
|
+
return requestAuthApi(this.apiOrigin, path, options);
|
|
53170
|
+
}
|
|
53171
|
+
}
|
|
51606
53172
|
export {
|
|
51607
53173
|
validateRunLifecycleEvent,
|
|
51608
53174
|
startedByFor,
|
|
@@ -51612,6 +53178,7 @@ export {
|
|
|
51612
53178
|
skillsCredentialFiles,
|
|
51613
53179
|
skillsCredentialFilePath,
|
|
51614
53180
|
settleRun,
|
|
53181
|
+
selectsSkillsLocalMode,
|
|
51615
53182
|
runTerminalSchema,
|
|
51616
53183
|
runProtocolSchema,
|
|
51617
53184
|
runPointersOf,
|
|
@@ -51639,6 +53206,7 @@ export {
|
|
|
51639
53206
|
leaseGenerationOf,
|
|
51640
53207
|
isValidSkillSlug,
|
|
51641
53208
|
isTerminalStatus,
|
|
53209
|
+
isSkillsLocalOptIn,
|
|
51642
53210
|
isActiveStatus,
|
|
51643
53211
|
getServerSkillMd,
|
|
51644
53212
|
getServerSkill,
|
|
@@ -51656,6 +53224,7 @@ export {
|
|
|
51656
53224
|
createRunStateMachine,
|
|
51657
53225
|
createRunService,
|
|
51658
53226
|
createRunEventEmitter,
|
|
53227
|
+
createRemoteSkillsClient,
|
|
51659
53228
|
createReceiptService,
|
|
51660
53229
|
createOfflineGate,
|
|
51661
53230
|
createImageProfileRegistry,
|
|
@@ -51677,9 +53246,17 @@ export {
|
|
|
51677
53246
|
SqliteRunExecutionStore,
|
|
51678
53247
|
SqliteGovernanceStore,
|
|
51679
53248
|
SkillsFleetCredentialError,
|
|
53249
|
+
SKILLS_LOCAL_OPT_IN_ENV_KEYS,
|
|
51680
53250
|
SKILLS_APP,
|
|
51681
53251
|
SKILLS_API_URL_ENV,
|
|
51682
53252
|
SKILLS_API_KEY_ENV,
|
|
53253
|
+
RemoteWorkspaceMemberError,
|
|
53254
|
+
RemoteSkillsClient,
|
|
53255
|
+
RemoteSkillsAuthClient,
|
|
53256
|
+
RemoteRouteUnsupportedError,
|
|
53257
|
+
RemoteRequestError,
|
|
53258
|
+
RemoteCreditApprovalError,
|
|
53259
|
+
RemoteCapabilityUnavailableError,
|
|
51683
53260
|
RUN_PROTOCOL_VERSION,
|
|
51684
53261
|
RUN_PROTOCOL_STATES,
|
|
51685
53262
|
RUN_LIFECYCLE_EVENT_TYPES,
|
|
@@ -51693,6 +53270,7 @@ export {
|
|
|
51693
53270
|
MemoryGovernanceStore,
|
|
51694
53271
|
LEGAL_TRANSITIONS,
|
|
51695
53272
|
ImageProfileResolutionError,
|
|
53273
|
+
HostedApiError,
|
|
51696
53274
|
GovernanceError,
|
|
51697
53275
|
GOVERNANCE_ERROR_CODES,
|
|
51698
53276
|
EcsDispatcher,
|