@hasna/skills 0.8.2 → 0.8.4
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 +70 -2
- package/bin/index.js +588 -285
- package/bin/mcp.js +255 -109
- package/bin/migrate.js +82 -24
- package/bin/server.js +1222 -430
- package/bin/worker.js +395 -87
- package/dist/cli/commands/grants.d.ts +2 -0
- package/dist/index.js +3 -3
- package/dist/lib/execution-grant-client.d.ts +5 -0
- package/dist/lib/execution-grants.d.ts +49 -0
- package/dist/lib/selected-manifest.d.ts +6 -0
- package/dist/lib/selected-run.d.ts +9 -0
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.js +9205 -8724
- package/dist/server/execution-grant-store.d.ts +29 -0
- package/dist/server/execution-grants-api.d.ts +4 -0
- package/dist/server/sqlite-store.d.ts +2 -0
- package/dist/server/store.d.ts +3 -0
- package/dist/server/types.d.ts +2 -0
- package/migrations/postgres/0009_execution_grants.sql +15 -0
- package/migrations/sqlite/0009_execution_grants.sql +15 -0
- package/package.json +1 -1
package/bin/mcp.js
CHANGED
|
@@ -20019,7 +20019,7 @@ var package_default;
|
|
|
20019
20019
|
var init_package = __esm(() => {
|
|
20020
20020
|
package_default = {
|
|
20021
20021
|
name: "@hasna/skills",
|
|
20022
|
-
version: "0.8.
|
|
20022
|
+
version: "0.8.4",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
|
@@ -54704,18 +54704,128 @@ var init_execution_secrets = __esm(() => {
|
|
|
54704
54704
|
init_selection_cache();
|
|
54705
54705
|
});
|
|
54706
54706
|
|
|
54707
|
-
// src/lib/
|
|
54708
|
-
|
|
54709
|
-
|
|
54710
|
-
|
|
54711
|
-
|
|
54712
|
-
|
|
54707
|
+
// src/lib/execution-grants.ts
|
|
54708
|
+
import { posix, win32 } from "path";
|
|
54709
|
+
function grantIdentifier(v) {
|
|
54710
|
+
return typeof v === "string" && /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(v) && !v.includes("..");
|
|
54711
|
+
}
|
|
54712
|
+
function grantRecord(v) {
|
|
54713
|
+
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
54714
|
+
}
|
|
54715
|
+
function keys(v, required2, optional3 = []) {
|
|
54716
|
+
return required2.every((k) => Object.hasOwn(v, k)) && Object.keys(v).every((k) => required2.includes(k) || optional3.includes(k));
|
|
54717
|
+
}
|
|
54718
|
+
function invalid6() {
|
|
54719
|
+
throw new Error("Invalid execution grant policy: use exact selections, named actors and consumers, and vault reference names only.");
|
|
54720
|
+
}
|
|
54721
|
+
function authority(v) {
|
|
54722
|
+
if (typeof v !== "string" || v.length > 2048 || /[\x00-\x20\x7f]/.test(v))
|
|
54723
|
+
return false;
|
|
54724
|
+
try {
|
|
54725
|
+
const u = new URL(v);
|
|
54726
|
+
return (u.protocol === "https:" || u.protocol === "http:" && ["127.0.0.1", "localhost", "[::1]"].includes(u.hostname)) && !u.username && !u.password && !u.search && !u.hash && u.pathname.endsWith("/v1") && u.href === v;
|
|
54727
|
+
} catch {
|
|
54728
|
+
return false;
|
|
54729
|
+
}
|
|
54730
|
+
}
|
|
54731
|
+
function pathFlavor(value) {
|
|
54732
|
+
return value.startsWith("/") ? posix : win32;
|
|
54733
|
+
}
|
|
54734
|
+
function grantWorkspace(v) {
|
|
54735
|
+
if (typeof v !== "string" || !v || v.length > 4096 || /[\x00-\x1f\x7f]/.test(v))
|
|
54736
|
+
return false;
|
|
54737
|
+
const flavor = pathFlavor(v);
|
|
54738
|
+
if (flavor === win32 && !/^(?:[A-Za-z]:\\|\\\\[^\\]+\\[^\\]+)/.test(v))
|
|
54739
|
+
return false;
|
|
54740
|
+
return flavor.isAbsolute(v) && flavor.normalize(v) === v;
|
|
54741
|
+
}
|
|
54742
|
+
function selection(v) {
|
|
54743
|
+
return grantRecord(v) && keys(v, ["slug", "version", "bundleDigest"]) && grantIdentifier(v.slug) && isValidSkillVersion(v.version) && typeof v.bundleDigest === "string" && /^sha256:[a-f0-9]{64}$/.test(v.bundleDigest);
|
|
54744
|
+
}
|
|
54745
|
+
function validateExecutionGrantRequest(value) {
|
|
54746
|
+
if (!grantRecord(value) || !keys(value, ["selection", "consumer"]) || !grantRecord(value.selection) || !keys(value.selection, [
|
|
54747
|
+
"authority",
|
|
54748
|
+
"workspaceId",
|
|
54749
|
+
"profileId",
|
|
54750
|
+
"profileRevision",
|
|
54751
|
+
"slug",
|
|
54752
|
+
"version",
|
|
54753
|
+
"bundleDigest"
|
|
54754
|
+
]) || !grantRecord(value.consumer) || !keys(value.consumer, ["stationId", "workspaceDirectory"]))
|
|
54755
|
+
invalid6();
|
|
54756
|
+
const { selection: s, consumer: c } = value;
|
|
54757
|
+
if (!selection({
|
|
54758
|
+
slug: s.slug,
|
|
54759
|
+
version: s.version,
|
|
54760
|
+
bundleDigest: s.bundleDigest
|
|
54761
|
+
}) || !authority(s.authority) || ![s.workspaceId, s.profileId, s.profileRevision, c.stationId].every(grantIdentifier) || !grantWorkspace(c.workspaceDirectory))
|
|
54762
|
+
invalid6();
|
|
54763
|
+
return structuredClone(value);
|
|
54764
|
+
}
|
|
54765
|
+
var MAX_EXECUTION_GRANT_BYTES;
|
|
54766
|
+
var init_execution_grants = __esm(() => {
|
|
54767
|
+
init_execution_secrets();
|
|
54768
|
+
init_skill_version();
|
|
54769
|
+
MAX_EXECUTION_GRANT_BYTES = 2 * 1024 * 1024;
|
|
54713
54770
|
});
|
|
54714
|
-
|
|
54715
|
-
|
|
54716
|
-
import {
|
|
54717
|
-
|
|
54718
|
-
|
|
54771
|
+
|
|
54772
|
+
// src/lib/execution-grant-client.ts
|
|
54773
|
+
import { isDeepStrictEqual } from "util";
|
|
54774
|
+
function id(value) {
|
|
54775
|
+
if (!grantIdentifier(value))
|
|
54776
|
+
throw new Error("Invalid execution grant profile or revision identifier.");
|
|
54777
|
+
return encodeURIComponent(value);
|
|
54778
|
+
}
|
|
54779
|
+
async function request(path, init = {}, authority2) {
|
|
54780
|
+
try {
|
|
54781
|
+
const connection = await resolveSkillsConnection();
|
|
54782
|
+
if (!connection)
|
|
54783
|
+
throw new Error;
|
|
54784
|
+
const configured = skillsApiRequestUrl(connection.apiOrigin, "/api/v1/").replace(/\/+$/, "");
|
|
54785
|
+
if (authority2 !== undefined && authority2 !== configured)
|
|
54786
|
+
throw new Error;
|
|
54787
|
+
const response = await fetch(skillsApiRequestUrl(connection.apiOrigin, `/api/v1${path}`), {
|
|
54788
|
+
...init,
|
|
54789
|
+
redirect: "error",
|
|
54790
|
+
credentials: "omit",
|
|
54791
|
+
signal: AbortSignal.timeout(15000),
|
|
54792
|
+
headers: {
|
|
54793
|
+
"Content-Type": "application/json",
|
|
54794
|
+
"User-Agent": "hasna-skills",
|
|
54795
|
+
Authorization: `Bearer ${connection.apiKey}`,
|
|
54796
|
+
...init.headers
|
|
54797
|
+
}
|
|
54798
|
+
});
|
|
54799
|
+
if (!response.ok) {
|
|
54800
|
+
response.body?.cancel().catch(() => {});
|
|
54801
|
+
throw new SkillSelectionError("EXECUTION_GRANT_UNAVAILABLE", `Skills execution grant request failed (HTTP ${response.status}); no fallback was attempted.`);
|
|
54802
|
+
}
|
|
54803
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, MAX_EXECUTION_GRANT_BYTES)));
|
|
54804
|
+
} catch (error61) {
|
|
54805
|
+
if (error61 instanceof SkillSelectionError)
|
|
54806
|
+
throw error61;
|
|
54807
|
+
throw new SkillSelectionError("EXECUTION_GRANT_UNAVAILABLE", "The configured Skills execution grant service could not be reached or returned an invalid response; no fallback was attempted.");
|
|
54808
|
+
}
|
|
54809
|
+
}
|
|
54810
|
+
async function resolveExecutionGrant(input2) {
|
|
54811
|
+
const snapshot = validateExecutionGrantRequest(input2);
|
|
54812
|
+
const value = await request(`/execution-grants/${id(snapshot.selection.profileId)}/resolve`, { method: "POST", body: JSON.stringify(snapshot) }, snapshot.selection.authority);
|
|
54813
|
+
if (!grantRecord(value) || Object.keys(value).length !== 3 || !grantIdentifier(value.policyRevision) || !grantIdentifier(value.grantId) || !grantRecord(value.bindings)) {
|
|
54814
|
+
throw new SkillSelectionError("INVALID_EXECUTION_GRANT", "The Skills API returned an invalid execution grant.");
|
|
54815
|
+
}
|
|
54816
|
+
if (!isDeepStrictEqual(value.bindings.selection, snapshot.selection) || !isDeepStrictEqual(value.bindings.consumer, snapshot.consumer)) {
|
|
54817
|
+
throw new SkillSelectionError("EXECUTION_GRANT_SCOPE_MISMATCH", "The Skills API returned a grant for a different selection or consumer.");
|
|
54818
|
+
}
|
|
54819
|
+
return value;
|
|
54820
|
+
}
|
|
54821
|
+
var init_execution_grant_client = __esm(() => {
|
|
54822
|
+
init_fleet_credentials();
|
|
54823
|
+
init_remote_files();
|
|
54824
|
+
init_selection_cache();
|
|
54825
|
+
init_execution_grants();
|
|
54826
|
+
});
|
|
54827
|
+
|
|
54828
|
+
// src/lib/selected-manifest.ts
|
|
54719
54829
|
function jsonEntry(entries, path) {
|
|
54720
54830
|
const entry = entries.find((candidate) => candidate.path === path);
|
|
54721
54831
|
if (!entry)
|
|
@@ -54736,11 +54846,28 @@ function describeEntries(entries) {
|
|
|
54736
54846
|
const kind = frontmatter?.kind === "instruction" || manifest.kind === "instruction" || packageJson.skills?.kind === "instruction" ? "instruction" : "executable";
|
|
54737
54847
|
return { kind, manifest, packageJson };
|
|
54738
54848
|
}
|
|
54849
|
+
var init_selected_manifest = __esm(() => {
|
|
54850
|
+
init_skill_validation();
|
|
54851
|
+
init_selection_cache();
|
|
54852
|
+
});
|
|
54853
|
+
|
|
54854
|
+
// src/lib/selected-run.ts
|
|
54855
|
+
var exports_selected_run = {};
|
|
54856
|
+
__export(exports_selected_run, {
|
|
54857
|
+
resolveSelectedRun: () => resolveSelectedRun,
|
|
54858
|
+
prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
|
|
54859
|
+
executeSelectedLocal: () => executeSelectedLocal
|
|
54860
|
+
});
|
|
54861
|
+
import { createHash as createHash9 } from "crypto";
|
|
54862
|
+
import { spawn } from "child_process";
|
|
54863
|
+
import { mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync10, realpathSync as realpathSync6 } from "fs";
|
|
54864
|
+
import { dirname as dirname8, join as join23, resolve as resolve5 } from "path";
|
|
54865
|
+
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
54739
54866
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
54740
54867
|
const context2 = await resolveSelectionContext(profileId, options);
|
|
54741
|
-
const
|
|
54742
|
-
const entries = await readSelectedEntries(
|
|
54743
|
-
return { selection, profileId: context2.receipt.profile.profileId, entries, ...describeEntries(entries), cacheDir: selectionCacheRoot(options) };
|
|
54868
|
+
const selection2 = exactProfileSelection(spec, context2.receipt.profile);
|
|
54869
|
+
const entries = await readSelectedEntries(selection2, context2, options);
|
|
54870
|
+
return { selection: selection2, profileId: context2.receipt.profile.profileId, entries, ...describeEntries(entries), cacheDir: selectionCacheRoot(options) };
|
|
54744
54871
|
}
|
|
54745
54872
|
async function prepareSelectedSecretBindings(selected, cwd = process.cwd()) {
|
|
54746
54873
|
const entries = await readCachedSelection(selected.selection, { cacheDir: selected.cacheDir });
|
|
@@ -54755,8 +54882,8 @@ async function prepareSelectedSecretBindings(selected, cwd = process.cwd()) {
|
|
|
54755
54882
|
return selectedSecretBindingsTemplate({ selection: selected.selection, profileId: selected.profileId, cwd }, names);
|
|
54756
54883
|
}
|
|
54757
54884
|
async function executeSelectedLocal(selected, options = {}) {
|
|
54758
|
-
const
|
|
54759
|
-
const entries = await readCachedSelection(
|
|
54885
|
+
const selection2 = structuredClone(selected.selection), profileId = selected.profileId;
|
|
54886
|
+
const entries = await readCachedSelection(selection2, { cacheDir: selected.cacheDir });
|
|
54760
54887
|
if (!entries)
|
|
54761
54888
|
throw new SkillSelectionError("CACHED_BUNDLE_MISSING", "The selected local execution bundle is not cached.");
|
|
54762
54889
|
const { kind, manifest, packageJson } = describeEntries(entries);
|
|
@@ -54800,9 +54927,12 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
54800
54927
|
const names = declaredSecretNames(runtime.env);
|
|
54801
54928
|
if (options.secretBindings !== undefined && options.env !== undefined)
|
|
54802
54929
|
throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Choose explicit vault bindings or SDK environment values, never both.");
|
|
54803
|
-
|
|
54930
|
+
let bindings = options.secretBindings === undefined ? undefined : validateSelectedSecretBindings(options.secretBindings, { selection: selection2, profileId, cwd: options.cwd ?? process.cwd() }, names);
|
|
54804
54931
|
let secretEnv = {};
|
|
54805
|
-
|
|
54932
|
+
const shared = names.length > 0 && options.secretBindings === undefined && options.env === undefined;
|
|
54933
|
+
if (shared && options.sharedExecutionGrants === false)
|
|
54934
|
+
throw new SkillSelectionError("EXECUTION_GRANT_FRESH_SELECTION_REQUIRED", "Shared secret grants require a fresh API selection; cached execution is refused.");
|
|
54935
|
+
if (!bindings && !shared)
|
|
54806
54936
|
for (const name of names) {
|
|
54807
54937
|
const value = options.env && Object.hasOwn(options.env, name) ? options.env[name] : undefined;
|
|
54808
54938
|
if (value === undefined)
|
|
@@ -54832,17 +54962,31 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
54832
54962
|
if (version2.exitCode !== 0 || actual !== runtime.version)
|
|
54833
54963
|
throw new SkillSelectionError("LOCAL_RUNTIME_VERSION_MISMATCH", "The installed runtime version differs from the version selected by the skill.");
|
|
54834
54964
|
}
|
|
54965
|
+
let executionGrant;
|
|
54966
|
+
if (shared) {
|
|
54967
|
+
const { authority: authority2, workspaceId, profileRevision, slug: slug2, version: version2, bundleDigest } = selection2;
|
|
54968
|
+
const request2 = {
|
|
54969
|
+
selection: { authority: authority2, workspaceId, profileId, profileRevision, slug: slug2, version: version2, bundleDigest },
|
|
54970
|
+
consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync6(options.cwd ?? process.cwd()) }
|
|
54971
|
+
};
|
|
54972
|
+
const grant = await (options.resolveExecutionGrant ?? resolveExecutionGrant)(request2);
|
|
54973
|
+
if (!grant || !grantIdentifier(grant.policyRevision) || !grantIdentifier(grant.grantId))
|
|
54974
|
+
throw new SkillSelectionError("INVALID_EXECUTION_GRANT", "The Skills API returned an invalid execution grant.");
|
|
54975
|
+
bindings = validateSelectedSecretBindings(grant.bindings, { selection: selection2, profileId, cwd: options.cwd ?? process.cwd() }, names);
|
|
54976
|
+
executionGrant = { policyRevision: grant.policyRevision, grantId: grant.grantId };
|
|
54977
|
+
}
|
|
54835
54978
|
if (bindings)
|
|
54836
54979
|
secretEnv = await resolveSelectedSecrets(bindings, options.createSecretsClient);
|
|
54837
54980
|
const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join23(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
|
|
54838
54981
|
result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
|
|
54839
54982
|
result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
|
|
54840
54983
|
const receipt = {
|
|
54841
|
-
selection,
|
|
54984
|
+
selection: selection2,
|
|
54842
54985
|
target: "local",
|
|
54843
54986
|
runtime: runtimeName,
|
|
54844
54987
|
inputDigest: `sha256:${createHash9("sha256").update(input2).digest("hex")}`,
|
|
54845
54988
|
runDirectory,
|
|
54989
|
+
...executionGrant ? { executionGrant } : {},
|
|
54846
54990
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
54847
54991
|
...result
|
|
54848
54992
|
};
|
|
@@ -54896,9 +55040,11 @@ async function subprocess(command, cwd, env, input2, timeoutMs) {
|
|
|
54896
55040
|
});
|
|
54897
55041
|
}
|
|
54898
55042
|
var init_selected_run = __esm(() => {
|
|
55043
|
+
init_execution_grant_client();
|
|
55044
|
+
init_execution_grants();
|
|
54899
55045
|
init_selection_resolver();
|
|
54900
55046
|
init_selection_cache();
|
|
54901
|
-
|
|
55047
|
+
init_selected_manifest();
|
|
54902
55048
|
init_execution_secrets();
|
|
54903
55049
|
});
|
|
54904
55050
|
|
|
@@ -54939,39 +55085,39 @@ class CloudExecutionClient {
|
|
|
54939
55085
|
}
|
|
54940
55086
|
return response;
|
|
54941
55087
|
}
|
|
54942
|
-
async submit(slug2, version2, input2, key,
|
|
55088
|
+
async submit(slug2, version2, input2, key, selection2) {
|
|
54943
55089
|
if (!/^[a-z0-9-]+$/.test(slug2) || !/^\d+\.\d+\.\d+$/.test(version2))
|
|
54944
55090
|
throw Error("Cloud execution requires skill@exact-version");
|
|
54945
55091
|
if (!/^[A-Za-z0-9._:-]{1,128}$/.test(key))
|
|
54946
55092
|
throw Error("Invalid idempotency key");
|
|
54947
|
-
if (
|
|
55093
|
+
if (selection2?.authority && selection2.authority !== skillsApiRequestUrl(this.apiOrigin, "/api/v1/").replace(/\/$/, ""))
|
|
54948
55094
|
throw Error("Selected skill belongs to another Skills authority");
|
|
54949
55095
|
const execution = parseExecution(await jsonBody(await this.request(slug2, "POST", {
|
|
54950
55096
|
version: version2,
|
|
54951
55097
|
input: input2,
|
|
54952
55098
|
idempotencyKey: key,
|
|
54953
|
-
...
|
|
54954
|
-
bundleDigest:
|
|
54955
|
-
workspaceId:
|
|
55099
|
+
...selection2 ? {
|
|
55100
|
+
bundleDigest: selection2.bundleDigest,
|
|
55101
|
+
workspaceId: selection2.workspaceId
|
|
54956
55102
|
} : {}
|
|
54957
55103
|
})));
|
|
54958
|
-
if (execution.skill !== slug2 || execution.version !== version2 ||
|
|
55104
|
+
if (execution.skill !== slug2 || execution.version !== version2 || selection2 && execution.bundleDigest.replace(/^sha256:/, "") !== selection2.bundleDigest.replace(/^sha256:/, ""))
|
|
54959
55105
|
throw Error("Cloud execution receipt does not match the selected exact skill");
|
|
54960
55106
|
return execution;
|
|
54961
55107
|
}
|
|
54962
|
-
async get(
|
|
54963
|
-
return parseExecution(await jsonBody(await this.request(runId(
|
|
55108
|
+
async get(id2) {
|
|
55109
|
+
return parseExecution(await jsonBody(await this.request(runId(id2))));
|
|
54964
55110
|
}
|
|
54965
|
-
async logs(
|
|
54966
|
-
return jsonBody(await this.request(runId(
|
|
55111
|
+
async logs(id2) {
|
|
55112
|
+
return jsonBody(await this.request(runId(id2) + "/logs"));
|
|
54967
55113
|
}
|
|
54968
|
-
async artifacts(
|
|
54969
|
-
return (await this.get(
|
|
55114
|
+
async artifacts(id2) {
|
|
55115
|
+
return (await this.get(id2)).artifacts;
|
|
54970
55116
|
}
|
|
54971
|
-
async download(
|
|
55117
|
+
async download(id2, name) {
|
|
54972
55118
|
if (!["document.pdf", "document.html"].includes(name))
|
|
54973
55119
|
throw Error("Invalid cloud artifact name");
|
|
54974
|
-
const response = await this.request(runId(
|
|
55120
|
+
const response = await this.request(runId(id2) + "/artifacts/" + encodeURIComponent(name));
|
|
54975
55121
|
if (!response.body)
|
|
54976
55122
|
throw Error("Cloud artifact body is missing");
|
|
54977
55123
|
const reader = response.body.getReader();
|
|
@@ -54990,16 +55136,16 @@ class CloudExecutionClient {
|
|
|
54990
55136
|
}
|
|
54991
55137
|
return Buffer.concat(chunks);
|
|
54992
55138
|
}
|
|
54993
|
-
async cancel(
|
|
54994
|
-
return parseExecution(await jsonBody(await this.request(runId(
|
|
55139
|
+
async cancel(id2) {
|
|
55140
|
+
return parseExecution(await jsonBody(await this.request(runId(id2) + "/cancel", "POST", {})));
|
|
54995
55141
|
}
|
|
54996
|
-
async wait(
|
|
55142
|
+
async wait(id2, options = {}) {
|
|
54997
55143
|
const timeout = options.timeoutMs ?? 300000, interval = options.intervalMs ?? 1000;
|
|
54998
55144
|
if (!Number.isFinite(timeout) || timeout < 1 || timeout > 1200000 || !Number.isFinite(interval) || interval < 100 || interval > 60000)
|
|
54999
55145
|
throw Error("Invalid cloud polling bounds");
|
|
55000
55146
|
const until = Date.now() + timeout;
|
|
55001
55147
|
for (;; ) {
|
|
55002
|
-
const run = await this.get(
|
|
55148
|
+
const run = await this.get(id2);
|
|
55003
55149
|
if (["succeeded", "failed", "cancelled"].includes(run.status))
|
|
55004
55150
|
return run;
|
|
55005
55151
|
if (Date.now() >= until)
|
|
@@ -55008,10 +55154,10 @@ class CloudExecutionClient {
|
|
|
55008
55154
|
}
|
|
55009
55155
|
}
|
|
55010
55156
|
}
|
|
55011
|
-
function runId(
|
|
55012
|
-
if (!/^run_[a-z0-9_]+$/.test(
|
|
55157
|
+
function runId(id2) {
|
|
55158
|
+
if (!/^run_[a-z0-9_]+$/.test(id2))
|
|
55013
55159
|
throw Error("Invalid cloud execution id");
|
|
55014
|
-
return
|
|
55160
|
+
return id2;
|
|
55015
55161
|
}
|
|
55016
55162
|
function parseExecution(value) {
|
|
55017
55163
|
const v = value;
|
|
@@ -55429,9 +55575,9 @@ function registerOperationTools(server) {
|
|
|
55429
55575
|
return mcpError("SELECTED_INPUT_REQUIRED", "The selected cloud execution contract accepts declared JSON input, not legacy run arguments or quote receipts.");
|
|
55430
55576
|
const { CloudExecutionClient: CloudExecutionClient2 } = await Promise.resolve().then(() => (init_cloud_executions(), exports_cloud_executions));
|
|
55431
55577
|
const client = await CloudExecutionClient2.configured();
|
|
55432
|
-
const
|
|
55433
|
-
const run = await client.submit(
|
|
55434
|
-
return mcpJson({ selection, remote: true, run });
|
|
55578
|
+
const selection2 = resolved.selection;
|
|
55579
|
+
const run = await client.submit(selection2.slug, selection2.version, input2 ?? {}, idempotency_key ?? crypto.randomUUID(), selection2);
|
|
55580
|
+
return mcpJson({ selection: selection2, remote: true, run });
|
|
55435
55581
|
}
|
|
55436
55582
|
const result2 = await executeSelectedLocal2(resolved, { args, input: input2, cwd: process.cwd() });
|
|
55437
55583
|
return { ...mcpJson(result2), isError: result2.exitCode !== 0 };
|
|
@@ -55866,9 +56012,9 @@ function registerResourceMetaTools(server) {
|
|
|
55866
56012
|
existing.last_seen_at = new Date().toISOString();
|
|
55867
56013
|
return mcpJson({ ...existing, registered: false });
|
|
55868
56014
|
}
|
|
55869
|
-
const
|
|
55870
|
-
const ag = { id, name: a.name, last_seen_at: new Date().toISOString() };
|
|
55871
|
-
_agentReg.set(
|
|
56015
|
+
const id2 = Math.random().toString(36).slice(2, 10);
|
|
56016
|
+
const ag = { id: id2, name: a.name, last_seen_at: new Date().toISOString() };
|
|
56017
|
+
_agentReg.set(id2, ag);
|
|
55872
56018
|
return mcpJson({ ...ag, registered: true });
|
|
55873
56019
|
});
|
|
55874
56020
|
server.tool("heartbeat", "Update last_seen_at to signal agent is active.", { agent_id: exports_external.string() }, async (a) => {
|
|
@@ -56059,11 +56205,11 @@ function addSchedule(skill, cron, options = {}) {
|
|
|
56059
56205
|
if (!valid)
|
|
56060
56206
|
return { schedule: null, error: error61 };
|
|
56061
56207
|
const data = loadSchedules(options.targetDir);
|
|
56062
|
-
const
|
|
56208
|
+
const id2 = `${skill}-${Date.now()}`;
|
|
56063
56209
|
const now = new Date;
|
|
56064
56210
|
const nextRun = getNextRun(cron, now);
|
|
56065
56211
|
const schedule = {
|
|
56066
|
-
id,
|
|
56212
|
+
id: id2,
|
|
56067
56213
|
name: options.name || `${skill} (${cron})`,
|
|
56068
56214
|
skill,
|
|
56069
56215
|
cron,
|
|
@@ -56569,11 +56715,11 @@ var init_private_publication_customer = __esm(() => {
|
|
|
56569
56715
|
});
|
|
56570
56716
|
|
|
56571
56717
|
// src/lib/private-publication-recovery.ts
|
|
56572
|
-
import { constants as constants8, closeSync as closeSync12, fsyncSync as fsyncSync2, fstatSync as fstatSync12, lstatSync as lstatSync10, mkdirSync as mkdirSync15, openSync as openSync12, readSync as readSync6, realpathSync as
|
|
56718
|
+
import { constants as constants8, closeSync as closeSync12, fsyncSync as fsyncSync2, fstatSync as fstatSync12, lstatSync as lstatSync10, mkdirSync as mkdirSync15, openSync as openSync12, readSync as readSync6, realpathSync as realpathSync7, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync13 } from "fs";
|
|
56573
56719
|
import { dirname as dirname11, isAbsolute as isAbsolute7, join as join28, resolve as resolve6 } from "path";
|
|
56574
56720
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
56575
56721
|
function safeDirectory(directory2) {
|
|
56576
|
-
if (!isAbsolute7(directory2) || directory2 !== resolve6(directory2) ||
|
|
56722
|
+
if (!isAbsolute7(directory2) || directory2 !== resolve6(directory2) || realpathSync7(directory2) !== directory2)
|
|
56577
56723
|
return fail2();
|
|
56578
56724
|
for (let path = directory2;; path = dirname11(path)) {
|
|
56579
56725
|
const stat2 = lstatSync10(path);
|
|
@@ -56711,7 +56857,7 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
|
|
|
56711
56857
|
phase: "prepared",
|
|
56712
56858
|
intent: null
|
|
56713
56859
|
};
|
|
56714
|
-
if (!isAbsolute7(recoveryDirectory) || resolve6(recoveryDirectory) !== recoveryDirectory ||
|
|
56860
|
+
if (!isAbsolute7(recoveryDirectory) || resolve6(recoveryDirectory) !== recoveryDirectory || realpathSync7(dirname11(recoveryDirectory)) !== dirname11(recoveryDirectory))
|
|
56715
56861
|
return fail2();
|
|
56716
56862
|
mkdirSync15(recoveryDirectory, { mode: 448 });
|
|
56717
56863
|
safeDirectory(recoveryDirectory);
|
|
@@ -57417,14 +57563,14 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57417
57563
|
return /* @__PURE__ */ new TypeError("Body is unusable");
|
|
57418
57564
|
}, rejectBodyUnusable = () => {
|
|
57419
57565
|
return Promise.reject(newBodyUnusableError());
|
|
57420
|
-
}, textDecoder, consumeBodyDirectOnce = (
|
|
57421
|
-
if (
|
|
57566
|
+
}, textDecoder, consumeBodyDirectOnce = (request2) => {
|
|
57567
|
+
if (request2[bodyConsumedDirectlyKey])
|
|
57422
57568
|
return rejectBodyUnusable();
|
|
57423
|
-
|
|
57569
|
+
request2[bodyConsumedDirectlyKey] = true;
|
|
57424
57570
|
}, toArrayBuffer = (buf) => {
|
|
57425
57571
|
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
57426
|
-
}, contentType = (
|
|
57427
|
-
return (
|
|
57572
|
+
}, contentType = (request2) => {
|
|
57573
|
+
return (request2[headersKey] ||= newHeadersFromIncoming(request2[incomingKey])).get("content-type") || "";
|
|
57428
57574
|
}, methodTokenRegExp, normalizeIncomingMethod = (method) => {
|
|
57429
57575
|
if (typeof method !== "string" || method.length === 0)
|
|
57430
57576
|
return "GET";
|
|
@@ -57457,57 +57603,57 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57457
57603
|
const normalized = method.toUpperCase();
|
|
57458
57604
|
if (normalized === "CONNECT" || normalized === "TRACK" || normalized === "TRACE" && method !== "TRACE")
|
|
57459
57605
|
return /* @__PURE__ */ new TypeError(`'${method}' HTTP method is unsupported.`);
|
|
57460
|
-
}, readBodyWithFastPath = (
|
|
57461
|
-
if (
|
|
57606
|
+
}, readBodyWithFastPath = (request2, method, fromBuffer) => {
|
|
57607
|
+
if (request2[bodyConsumedDirectlyKey])
|
|
57462
57608
|
return rejectBodyUnusable();
|
|
57463
|
-
const methodName =
|
|
57609
|
+
const methodName = request2.method;
|
|
57464
57610
|
if (methodName === "GET" || methodName === "HEAD")
|
|
57465
|
-
return
|
|
57611
|
+
return request2[getRequestCache]()[method]();
|
|
57466
57612
|
const methodValidationError = validateDirectReadMethod(methodName);
|
|
57467
57613
|
if (methodValidationError)
|
|
57468
57614
|
return Promise.reject(methodValidationError);
|
|
57469
|
-
if (
|
|
57615
|
+
if (request2[requestCache]) {
|
|
57470
57616
|
if (methodName !== "TRACE")
|
|
57471
|
-
return
|
|
57617
|
+
return request2[requestCache][method]();
|
|
57472
57618
|
}
|
|
57473
|
-
const alreadyUsedError = consumeBodyDirectOnce(
|
|
57619
|
+
const alreadyUsedError = consumeBodyDirectOnce(request2);
|
|
57474
57620
|
if (alreadyUsedError)
|
|
57475
57621
|
return alreadyUsedError;
|
|
57476
|
-
const raw = readRawBodyIfAvailable(
|
|
57622
|
+
const raw = readRawBodyIfAvailable(request2);
|
|
57477
57623
|
if (raw) {
|
|
57478
|
-
const result = Promise.resolve(fromBuffer(raw,
|
|
57479
|
-
|
|
57624
|
+
const result = Promise.resolve(fromBuffer(raw, request2));
|
|
57625
|
+
request2[bodyBufferKey] = undefined;
|
|
57480
57626
|
return result;
|
|
57481
57627
|
}
|
|
57482
|
-
return readBodyDirect(
|
|
57483
|
-
const result = fromBuffer(buf,
|
|
57484
|
-
|
|
57628
|
+
return readBodyDirect(request2).then((buf) => {
|
|
57629
|
+
const result = fromBuffer(buf, request2);
|
|
57630
|
+
request2[bodyBufferKey] = undefined;
|
|
57485
57631
|
return result;
|
|
57486
57632
|
});
|
|
57487
|
-
}, readRawBodyIfAvailable = (
|
|
57488
|
-
const incoming =
|
|
57633
|
+
}, readRawBodyIfAvailable = (request2) => {
|
|
57634
|
+
const incoming = request2[incomingKey];
|
|
57489
57635
|
if ("rawBody" in incoming && incoming.rawBody instanceof Buffer)
|
|
57490
57636
|
return incoming.rawBody;
|
|
57491
|
-
}, normalizeAbortError = (
|
|
57637
|
+
}, normalizeAbortError = (request2, incoming) => {
|
|
57492
57638
|
if (incoming.errored)
|
|
57493
57639
|
return incoming.errored;
|
|
57494
|
-
const reason =
|
|
57640
|
+
const reason = request2[abortReasonKey];
|
|
57495
57641
|
if (reason !== undefined)
|
|
57496
57642
|
return reason instanceof Error ? reason : new Error(String(reason));
|
|
57497
57643
|
return /* @__PURE__ */ new Error("Client connection prematurely closed.");
|
|
57498
|
-
}, readBodyDirect = (
|
|
57499
|
-
if (
|
|
57500
|
-
return Promise.resolve(
|
|
57501
|
-
if (
|
|
57502
|
-
return
|
|
57503
|
-
const incoming =
|
|
57644
|
+
}, readBodyDirect = (request2) => {
|
|
57645
|
+
if (request2[bodyBufferKey])
|
|
57646
|
+
return Promise.resolve(request2[bodyBufferKey]);
|
|
57647
|
+
if (request2[bodyReadPromiseKey])
|
|
57648
|
+
return request2[bodyReadPromiseKey];
|
|
57649
|
+
const incoming = request2[incomingKey];
|
|
57504
57650
|
if (incoming.readableDidRead)
|
|
57505
57651
|
return rejectBodyUnusable();
|
|
57506
57652
|
const buffered = readBodyBufferedBeforeDisconnect(incoming);
|
|
57507
57653
|
if (buffered !== undefined) {
|
|
57508
57654
|
if (buffered instanceof Error)
|
|
57509
57655
|
return Promise.reject(buffered);
|
|
57510
|
-
|
|
57656
|
+
request2[bodyBufferKey] = buffered;
|
|
57511
57657
|
return Promise.resolve(buffered);
|
|
57512
57658
|
}
|
|
57513
57659
|
const promise3 = new Promise((resolve7, reject) => {
|
|
@@ -57529,9 +57675,9 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57529
57675
|
if (recovered instanceof Error)
|
|
57530
57676
|
reject(recovered);
|
|
57531
57677
|
else if (recovered === undefined)
|
|
57532
|
-
reject(error61 ?? normalizeAbortError(
|
|
57678
|
+
reject(error61 ?? normalizeAbortError(request2, incoming));
|
|
57533
57679
|
else {
|
|
57534
|
-
|
|
57680
|
+
request2[bodyBufferKey] = recovered;
|
|
57535
57681
|
resolve7(recovered);
|
|
57536
57682
|
}
|
|
57537
57683
|
});
|
|
@@ -57543,7 +57689,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57543
57689
|
const onEnd = () => {
|
|
57544
57690
|
finish(() => {
|
|
57545
57691
|
const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
|
|
57546
|
-
|
|
57692
|
+
request2[bodyBufferKey] = buffer;
|
|
57547
57693
|
resolve7(buffer);
|
|
57548
57694
|
});
|
|
57549
57695
|
};
|
|
@@ -57562,7 +57708,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57562
57708
|
if (recoverCompleteBodyAfterDisconnect())
|
|
57563
57709
|
return;
|
|
57564
57710
|
finish(() => {
|
|
57565
|
-
reject(normalizeAbortError(
|
|
57711
|
+
reject(normalizeAbortError(request2, incoming));
|
|
57566
57712
|
});
|
|
57567
57713
|
};
|
|
57568
57714
|
const cleanup = () => {
|
|
@@ -57570,7 +57716,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57570
57716
|
incoming.off("end", onEnd);
|
|
57571
57717
|
incoming.off("error", onError);
|
|
57572
57718
|
incoming.off("close", onClose);
|
|
57573
|
-
|
|
57719
|
+
request2[bodyReadPromiseKey] = undefined;
|
|
57574
57720
|
};
|
|
57575
57721
|
incoming.on("data", onData);
|
|
57576
57722
|
incoming.on("end", onEnd);
|
|
@@ -57587,7 +57733,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57587
57733
|
onClose();
|
|
57588
57734
|
});
|
|
57589
57735
|
});
|
|
57590
|
-
|
|
57736
|
+
request2[bodyReadPromiseKey] = promise3;
|
|
57591
57737
|
return promise3;
|
|
57592
57738
|
}, requestPrototype, newRequest = (incoming, defaultHostname) => {
|
|
57593
57739
|
const req = Object.create(requestPrototype);
|
|
@@ -58162,10 +58308,10 @@ var init_dist2 = __esm(() => {
|
|
|
58162
58308
|
get body() {
|
|
58163
58309
|
if (!this[bodyConsumedDirectlyKey])
|
|
58164
58310
|
return this[getRequestCache]().body;
|
|
58165
|
-
const
|
|
58166
|
-
if (!this[bodyLockReaderKey] &&
|
|
58167
|
-
this[bodyLockReaderKey] =
|
|
58168
|
-
return
|
|
58311
|
+
const request2 = this[getRequestCache]();
|
|
58312
|
+
if (!this[bodyLockReaderKey] && request2.body)
|
|
58313
|
+
this[bodyLockReaderKey] = request2.body.getReader();
|
|
58314
|
+
return request2.body;
|
|
58169
58315
|
},
|
|
58170
58316
|
get bodyUsed() {
|
|
58171
58317
|
if (this[bodyConsumedDirectlyKey])
|
|
@@ -58210,8 +58356,8 @@ var init_dist2 = __esm(() => {
|
|
|
58210
58356
|
return readBodyWithFastPath(this, "arrayBuffer", (buf) => toArrayBuffer(buf));
|
|
58211
58357
|
} });
|
|
58212
58358
|
Object.defineProperty(requestPrototype, "blob", { value: function() {
|
|
58213
|
-
return readBodyWithFastPath(this, "blob", (buf,
|
|
58214
|
-
const type = contentType(
|
|
58359
|
+
return readBodyWithFastPath(this, "blob", (buf, request2) => {
|
|
58360
|
+
const type = contentType(request2);
|
|
58215
58361
|
const init = type ? { headers: { "content-type": type } } : undefined;
|
|
58216
58362
|
return new Response(buf, init).blob();
|
|
58217
58363
|
});
|
|
@@ -59255,28 +59401,28 @@ data:
|
|
|
59255
59401
|
}
|
|
59256
59402
|
if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
|
|
59257
59403
|
this._requestResponseMap.set(requestId, message);
|
|
59258
|
-
const relatedIds = Array.from(this._requestToStreamMapping.entries()).filter(([_, sid]) => sid === streamId).map(([
|
|
59259
|
-
const allResponsesReady = relatedIds.every((
|
|
59404
|
+
const relatedIds = Array.from(this._requestToStreamMapping.entries()).filter(([_, sid]) => sid === streamId).map(([id2]) => id2);
|
|
59405
|
+
const allResponsesReady = relatedIds.every((id2) => this._requestResponseMap.has(id2));
|
|
59260
59406
|
if (allResponsesReady) {
|
|
59261
59407
|
if (!stream) {
|
|
59262
59408
|
if (this._closed) {
|
|
59263
|
-
for (const
|
|
59264
|
-
this._requestResponseMap.delete(
|
|
59265
|
-
this._requestToStreamMapping.delete(
|
|
59409
|
+
for (const id2 of relatedIds) {
|
|
59410
|
+
this._requestResponseMap.delete(id2);
|
|
59411
|
+
this._requestToStreamMapping.delete(id2);
|
|
59266
59412
|
}
|
|
59267
59413
|
return;
|
|
59268
59414
|
}
|
|
59269
59415
|
if (!this._enableJsonResponse && this._eventStore && this._resumableStreams.has(streamId)) {
|
|
59270
|
-
for (const
|
|
59271
|
-
this._requestResponseMap.delete(
|
|
59272
|
-
this._requestToStreamMapping.delete(
|
|
59416
|
+
for (const id2 of relatedIds) {
|
|
59417
|
+
this._requestResponseMap.delete(id2);
|
|
59418
|
+
this._requestToStreamMapping.delete(id2);
|
|
59273
59419
|
}
|
|
59274
59420
|
this._resumableStreams.delete(streamId);
|
|
59275
59421
|
return;
|
|
59276
59422
|
}
|
|
59277
|
-
for (const
|
|
59278
|
-
this._requestResponseMap.delete(
|
|
59279
|
-
this._requestToStreamMapping.delete(
|
|
59423
|
+
for (const id2 of relatedIds) {
|
|
59424
|
+
this._requestResponseMap.delete(id2);
|
|
59425
|
+
this._requestToStreamMapping.delete(id2);
|
|
59280
59426
|
}
|
|
59281
59427
|
throw new Error(`No connection established for request ID: ${String(requestId)}`);
|
|
59282
59428
|
}
|
|
@@ -59287,7 +59433,7 @@ data:
|
|
|
59287
59433
|
if (this.sessionId !== undefined) {
|
|
59288
59434
|
headers["mcp-session-id"] = this.sessionId;
|
|
59289
59435
|
}
|
|
59290
|
-
const responses = relatedIds.map((
|
|
59436
|
+
const responses = relatedIds.map((id2) => this._requestResponseMap.get(id2));
|
|
59291
59437
|
if (responses.length === 1) {
|
|
59292
59438
|
stream.resolveJson(new Response(JSON.stringify(responses[0]), { status: 200, headers }));
|
|
59293
59439
|
} else {
|
|
@@ -59296,9 +59442,9 @@ data:
|
|
|
59296
59442
|
} else {
|
|
59297
59443
|
stream.cleanup();
|
|
59298
59444
|
}
|
|
59299
|
-
for (const
|
|
59300
|
-
this._requestResponseMap.delete(
|
|
59301
|
-
this._requestToStreamMapping.delete(
|
|
59445
|
+
for (const id2 of relatedIds) {
|
|
59446
|
+
this._requestResponseMap.delete(id2);
|
|
59447
|
+
this._requestToStreamMapping.delete(id2);
|
|
59302
59448
|
}
|
|
59303
59449
|
this._resumableStreams.delete(streamId);
|
|
59304
59450
|
}
|