@enactprotocol/cli 1.2.8 → 1.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +228 -26
- package/dist/index.js.bak +228 -26
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -214775,6 +214775,13 @@ class EnactApiClient {
|
|
|
214775
214775
|
throw new EnactApiError("Unknown error occurred", 0);
|
|
214776
214776
|
}
|
|
214777
214777
|
}
|
|
214778
|
+
async signTool(toolId, payload, token, tokenType = "cli") {
|
|
214779
|
+
const endpoint = `/functions/v1/tools/${encodeURIComponent(toolId)}/signatures`;
|
|
214780
|
+
return this.makeRequest(endpoint, {
|
|
214781
|
+
method: "POST",
|
|
214782
|
+
body: JSON.stringify(payload)
|
|
214783
|
+
}, token, tokenType);
|
|
214784
|
+
}
|
|
214778
214785
|
generateOAuthUrl(options) {
|
|
214779
214786
|
const params = new URLSearchParams({
|
|
214780
214787
|
response_type: "code",
|
|
@@ -229706,6 +229713,33 @@ class EnactCore {
|
|
|
229706
229713
|
};
|
|
229707
229714
|
}
|
|
229708
229715
|
}
|
|
229716
|
+
static async checkToolVerificationStatus(tool) {
|
|
229717
|
+
const documentForVerification = {
|
|
229718
|
+
command: tool.command,
|
|
229719
|
+
description: tool.description,
|
|
229720
|
+
from: tool.from,
|
|
229721
|
+
name: tool.name,
|
|
229722
|
+
signatures: tool.signatures?.map((sig) => ({
|
|
229723
|
+
signature: sig.value,
|
|
229724
|
+
publicKey: "",
|
|
229725
|
+
algorithm: sig.algorithm,
|
|
229726
|
+
timestamp: new Date(sig.created).getTime()
|
|
229727
|
+
}))
|
|
229728
|
+
};
|
|
229729
|
+
let isValid = false;
|
|
229730
|
+
if (tool.signatures && tool.signatures.length > 0) {
|
|
229731
|
+
isValid = tool.signatures.some((sig) => {
|
|
229732
|
+
const referenceSignature = {
|
|
229733
|
+
signature: sig.value,
|
|
229734
|
+
publicKey: "",
|
|
229735
|
+
algorithm: sig.algorithm,
|
|
229736
|
+
timestamp: new Date(sig.created).getTime()
|
|
229737
|
+
};
|
|
229738
|
+
return SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ["command", "description", "from", "name"] });
|
|
229739
|
+
});
|
|
229740
|
+
}
|
|
229741
|
+
return isValid;
|
|
229742
|
+
}
|
|
229709
229743
|
async verifyTool(tool, dangerouslySkipVerification = false) {
|
|
229710
229744
|
if (dangerouslySkipVerification) {
|
|
229711
229745
|
logger_default.warn(`Skipping signature verification for tool: ${tool.name}`);
|
|
@@ -229715,23 +229749,8 @@ class EnactCore {
|
|
|
229715
229749
|
if (!tool.signatures || tool.signatures.length === 0) {
|
|
229716
229750
|
throw new Error(`Tool ${tool.name} does not have any signatures`);
|
|
229717
229751
|
}
|
|
229718
|
-
const
|
|
229719
|
-
|
|
229720
|
-
description: tool.description,
|
|
229721
|
-
from: tool.from,
|
|
229722
|
-
name: tool.name
|
|
229723
|
-
};
|
|
229724
|
-
const referenceSignature = {
|
|
229725
|
-
signature: tool.signatures[0].value,
|
|
229726
|
-
publicKey: "",
|
|
229727
|
-
algorithm: tool.signatures[0].algorithm,
|
|
229728
|
-
timestamp: new Date(tool.signatures[0].created).getTime()
|
|
229729
|
-
};
|
|
229730
|
-
const canonicalDoc = SigningService.getCanonicalDocument(documentForVerification, { includeFields: ["command", "description", "from", "name"] });
|
|
229731
|
-
const docString = JSON.stringify(canonicalDoc);
|
|
229732
|
-
const messageHash = CryptoUtils.hash(docString);
|
|
229733
|
-
const directVerify = CryptoUtils.verify(referenceSignature.publicKey, messageHash, referenceSignature.signature);
|
|
229734
|
-
const isValid = SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ["command", "description", "from", "name"] });
|
|
229752
|
+
const isValid = await EnactCore.checkToolVerificationStatus(tool);
|
|
229753
|
+
console.log("Final verification result:", isValid);
|
|
229735
229754
|
if (!isValid) {
|
|
229736
229755
|
throw new Error(`Tool ${tool.name} has invalid signatures`);
|
|
229737
229756
|
}
|
|
@@ -230085,9 +230104,11 @@ ${import_picocolors13.default.bold("EXAMPLES:")}
|
|
|
230085
230104
|
try {
|
|
230086
230105
|
const tool = await apiClient.getTool(result.name);
|
|
230087
230106
|
if (tool) {
|
|
230107
|
+
const isValid = await EnactCore.checkToolVerificationStatus(tool);
|
|
230088
230108
|
const enactTool = {
|
|
230089
230109
|
name: tool.name,
|
|
230090
230110
|
description: tool.description || "",
|
|
230111
|
+
verified: isValid,
|
|
230091
230112
|
command: tool.command,
|
|
230092
230113
|
from: tool.from,
|
|
230093
230114
|
version: tool.version || "1.0.0",
|
|
@@ -230269,6 +230290,159 @@ async function collectParametersInteractively(inputSchema) {
|
|
|
230269
230290
|
}
|
|
230270
230291
|
return params;
|
|
230271
230292
|
}
|
|
230293
|
+
async function handleSignToolCommand(args, options) {
|
|
230294
|
+
if (options.help) {
|
|
230295
|
+
console.error(`
|
|
230296
|
+
Usage: enact sign [options]
|
|
230297
|
+
Sign a tool definition using your private key
|
|
230298
|
+
Options:
|
|
230299
|
+
--help, -h Show this help message
|
|
230300
|
+
--tool query Search for the tool to sign (name)
|
|
230301
|
+
Examples:
|
|
230302
|
+
enact sign --tool myorg/mytool
|
|
230303
|
+
`);
|
|
230304
|
+
return;
|
|
230305
|
+
}
|
|
230306
|
+
if (!options.tool) {
|
|
230307
|
+
const inputSchema = {
|
|
230308
|
+
type: "object",
|
|
230309
|
+
properties: {
|
|
230310
|
+
toolName: {
|
|
230311
|
+
type: "string",
|
|
230312
|
+
description: "The name of the tool to run"
|
|
230313
|
+
}
|
|
230314
|
+
},
|
|
230315
|
+
required: ["tool"]
|
|
230316
|
+
};
|
|
230317
|
+
const params = await collectParametersInteractively(inputSchema);
|
|
230318
|
+
options.tool = params.toolName;
|
|
230319
|
+
}
|
|
230320
|
+
const spinner = Y2();
|
|
230321
|
+
spinner.start("Searching for tools...");
|
|
230322
|
+
const results = [];
|
|
230323
|
+
try {
|
|
230324
|
+
const searchOptions = {
|
|
230325
|
+
query: options.tool ? options.tool : "",
|
|
230326
|
+
limit: 20,
|
|
230327
|
+
tags: undefined,
|
|
230328
|
+
author: undefined,
|
|
230329
|
+
format: "table"
|
|
230330
|
+
};
|
|
230331
|
+
const apiClient = await EnactApiClient.create();
|
|
230332
|
+
const searchResults = await apiClient.searchTools(searchOptions);
|
|
230333
|
+
for (const result of searchResults) {
|
|
230334
|
+
if (result.name) {
|
|
230335
|
+
try {
|
|
230336
|
+
const tool = await apiClient.getTool(result.name);
|
|
230337
|
+
if (tool) {
|
|
230338
|
+
const documentForVerification2 = {
|
|
230339
|
+
command: tool.command,
|
|
230340
|
+
description: tool.description,
|
|
230341
|
+
from: tool.from,
|
|
230342
|
+
name: tool.name
|
|
230343
|
+
};
|
|
230344
|
+
const isValid = await EnactCore.checkToolVerificationStatus(tool);
|
|
230345
|
+
const enactTool = {
|
|
230346
|
+
name: tool.name,
|
|
230347
|
+
description: tool.description || "",
|
|
230348
|
+
verified: isValid,
|
|
230349
|
+
command: tool.command,
|
|
230350
|
+
from: tool.from,
|
|
230351
|
+
version: tool.version || "1.0.0",
|
|
230352
|
+
timeout: tool.timeout,
|
|
230353
|
+
tags: tool.tags || [],
|
|
230354
|
+
inputSchema: tool.inputSchema,
|
|
230355
|
+
outputSchema: tool.outputSchema,
|
|
230356
|
+
env: tool.env_vars ? Object.fromEntries(Object.entries(tool.env_vars).map(([key, config2]) => [
|
|
230357
|
+
key,
|
|
230358
|
+
{ ...config2, source: config2.source || "env" }
|
|
230359
|
+
])) : undefined,
|
|
230360
|
+
signature: tool.signature,
|
|
230361
|
+
signatures: Array.isArray(tool.signatures) ? tool.signatures : tool.signatures ? Object.values(tool.signatures) : undefined,
|
|
230362
|
+
namespace: tool.namespace,
|
|
230363
|
+
resources: tool.resources,
|
|
230364
|
+
license: tool.license,
|
|
230365
|
+
authors: tool.authors,
|
|
230366
|
+
examples: tool.examples,
|
|
230367
|
+
annotations: tool.annotations
|
|
230368
|
+
};
|
|
230369
|
+
results.push(enactTool);
|
|
230370
|
+
}
|
|
230371
|
+
} catch (error2) {
|
|
230372
|
+
continue;
|
|
230373
|
+
}
|
|
230374
|
+
}
|
|
230375
|
+
}
|
|
230376
|
+
spinner.stop(`Found ${results.length} tool${results.length === 1 ? "" : "s"}`);
|
|
230377
|
+
if (results.length === 0) {
|
|
230378
|
+
Me("No tools found matching your criteria.", "No Results");
|
|
230379
|
+
Me(`Try:
|
|
230380
|
+
• Broader keywords
|
|
230381
|
+
• Removing filters
|
|
230382
|
+
• Different spelling`, "Suggestions");
|
|
230383
|
+
return;
|
|
230384
|
+
}
|
|
230385
|
+
} catch (error2) {
|
|
230386
|
+
spinner.stop("Search failed");
|
|
230387
|
+
if (error2.message?.includes("ENOTFOUND") || error2.message?.includes("ECONNREFUSED")) {
|
|
230388
|
+
Me("Could not connect to the Enact registry. Check your internet connection.", "Connection Error");
|
|
230389
|
+
} else {
|
|
230390
|
+
Me(error2 instanceof Error ? error2.message : String(error2), "Error");
|
|
230391
|
+
}
|
|
230392
|
+
console.error(import_picocolors13.default.red(`Search failed: ${error2 instanceof Error ? error2.message : String(error2)}`));
|
|
230393
|
+
process.exit(1);
|
|
230394
|
+
}
|
|
230395
|
+
const selected_tool = await ve({
|
|
230396
|
+
message: "Select a tool to sign:",
|
|
230397
|
+
options: results.map((tool) => ({
|
|
230398
|
+
value: tool,
|
|
230399
|
+
label: `${tool.name} - ${tool.description.substring(0, 60)}${tool.description.length > 60 ? "..." : ""} - Verified: ${tool.verified ? import_picocolors13.default.green("Yes") : import_picocolors13.default.red("No")}`
|
|
230400
|
+
}))
|
|
230401
|
+
});
|
|
230402
|
+
const documentForVerification = {
|
|
230403
|
+
command: selected_tool.command,
|
|
230404
|
+
description: selected_tool.description,
|
|
230405
|
+
from: selected_tool.from,
|
|
230406
|
+
name: selected_tool.name
|
|
230407
|
+
};
|
|
230408
|
+
const privateKeys = await KeyManager.getAllPrivateKeys();
|
|
230409
|
+
const privateKey = await ve({
|
|
230410
|
+
message: "Select a private key to sign with:",
|
|
230411
|
+
options: privateKeys.map((key) => ({
|
|
230412
|
+
value: key,
|
|
230413
|
+
label: `${key.fileName}`
|
|
230414
|
+
}))
|
|
230415
|
+
});
|
|
230416
|
+
const TrustedKey = CryptoUtils.getPublicKeyFromPrivate(privateKey.key);
|
|
230417
|
+
if (selected_tool.signatures && selected_tool.signatures.length > 0) {
|
|
230418
|
+
const alreadySigned = selected_tool.signatures.some((sig) => {
|
|
230419
|
+
const referenceSignature = {
|
|
230420
|
+
signature: sig.value,
|
|
230421
|
+
publicKey: "",
|
|
230422
|
+
algorithm: sig.algorithm,
|
|
230423
|
+
timestamp: new Date(sig.created).getTime()
|
|
230424
|
+
};
|
|
230425
|
+
return SigningService.verifyDocumentWithPublicKey(documentForVerification, referenceSignature, TrustedKey, { includeFields: ["command", "description", "from", "name"] });
|
|
230426
|
+
});
|
|
230427
|
+
if (alreadySigned) {
|
|
230428
|
+
console.log(import_picocolors13.default.green("✓ Tool has already been signed with the selected key."));
|
|
230429
|
+
return;
|
|
230430
|
+
}
|
|
230431
|
+
}
|
|
230432
|
+
const spinnerSign = Y2();
|
|
230433
|
+
console.error(spinnerSign.start("Signing tool..."));
|
|
230434
|
+
const signature = await SigningService.signDocument(documentForVerification, privateKey.key, { includeFields: ["command", "description", "from", "name"] });
|
|
230435
|
+
spinnerSign.stop(import_picocolors13.default.green("✓ Tool signed successfully"));
|
|
230436
|
+
console.error(import_picocolors13.default.cyan(`
|
|
230437
|
+
Signature Details:`));
|
|
230438
|
+
console.error(import_picocolors13.default.cyan(` Signature: ${signature.signature}`));
|
|
230439
|
+
console.error(import_picocolors13.default.cyan(` Algorithm: ${signature.algorithm}`));
|
|
230440
|
+
console.error(import_picocolors13.default.cyan(` Created: ${new Date(signature.timestamp).toISOString()}`));
|
|
230441
|
+
console.error(import_picocolors13.default.cyan(` Public Key: ${TrustedKey}`));
|
|
230442
|
+
console.error(import_picocolors13.default.red(`
|
|
230443
|
+
Pushing the signature to the registry is not yet implemented.`));
|
|
230444
|
+
return signature;
|
|
230445
|
+
}
|
|
230272
230446
|
async function handleCoreExecCommand(args, options) {
|
|
230273
230447
|
if (options.help) {
|
|
230274
230448
|
console.error(`
|
|
@@ -230510,6 +230684,7 @@ Environment variables:`));
|
|
|
230510
230684
|
const enactTool = {
|
|
230511
230685
|
name: toolDefinition.name,
|
|
230512
230686
|
description: toolDefinition.description || "",
|
|
230687
|
+
verified: true,
|
|
230513
230688
|
command: toolDefinition.command,
|
|
230514
230689
|
from: toolDefinition.from,
|
|
230515
230690
|
version: toolDefinition.version || "1.0.0",
|
|
@@ -230676,9 +230851,11 @@ ${import_picocolors13.default.bold("EXAMPLES:")}
|
|
|
230676
230851
|
Se(import_picocolors13.default.red(`Tool not found: ${toolName}`));
|
|
230677
230852
|
process.exit(1);
|
|
230678
230853
|
}
|
|
230854
|
+
const isValid = EnactCore.checkToolVerificationStatus(toolDefinition);
|
|
230679
230855
|
const tool = {
|
|
230680
230856
|
name: toolDefinition.name,
|
|
230681
230857
|
description: toolDefinition.description || "",
|
|
230858
|
+
verified: isValid,
|
|
230682
230859
|
command: toolDefinition.command,
|
|
230683
230860
|
from: toolDefinition.from,
|
|
230684
230861
|
version: toolDefinition.version || "1.0.0",
|
|
@@ -230717,6 +230894,11 @@ ${import_picocolors13.default.bold(import_picocolors13.default.cyan(`\uD83D\uDCE
|
|
|
230717
230894
|
if (tool.command) {
|
|
230718
230895
|
console.error(`${import_picocolors13.default.bold("Command:")} ${import_picocolors13.default.gray(tool.command)}`);
|
|
230719
230896
|
}
|
|
230897
|
+
if (tool.verified) {
|
|
230898
|
+
console.error(`${import_picocolors13.default.bold("Verification:")} ${import_picocolors13.default.green("Verified ✓")}`);
|
|
230899
|
+
} else {
|
|
230900
|
+
console.error(`${import_picocolors13.default.bold("Verification:")} ${import_picocolors13.default.red("Unverified ✗")}`);
|
|
230901
|
+
}
|
|
230720
230902
|
if (tool.from) {
|
|
230721
230903
|
console.error(`${import_picocolors13.default.bold("Container:")} ${import_picocolors13.default.gray(tool.from)}`);
|
|
230722
230904
|
}
|
|
@@ -230767,20 +230949,25 @@ ${import_picocolors13.default.bold("Examples:")}`);
|
|
|
230767
230949
|
function displayResultsTable(results) {
|
|
230768
230950
|
console.error(`
|
|
230769
230951
|
` + import_picocolors13.default.bold("Search Results:"));
|
|
230770
|
-
console.error("═".repeat(100));
|
|
230771
230952
|
const nameWidth = 40;
|
|
230953
|
+
const statusWidth = 15;
|
|
230772
230954
|
const descWidth = 45;
|
|
230773
230955
|
const tagsWidth = 20;
|
|
230774
|
-
|
|
230775
|
-
console.error(
|
|
230956
|
+
const totalWidth = nameWidth + statusWidth + descWidth + tagsWidth + 9;
|
|
230957
|
+
console.error(import_picocolors13.default.gray("═".repeat(totalWidth)));
|
|
230958
|
+
console.error(import_picocolors13.default.bold(import_picocolors13.default.white("NAME".padEnd(nameWidth))) + import_picocolors13.default.gray(" │ ") + import_picocolors13.default.bold(import_picocolors13.default.white("STATUS".padEnd(statusWidth))) + import_picocolors13.default.gray(" │ ") + import_picocolors13.default.bold(import_picocolors13.default.white("DESCRIPTION".padEnd(descWidth))) + import_picocolors13.default.gray(" │ ") + import_picocolors13.default.bold(import_picocolors13.default.white("TAGS".padEnd(tagsWidth))));
|
|
230959
|
+
console.error(import_picocolors13.default.gray("─".repeat(nameWidth) + "─┼─" + "─".repeat(statusWidth) + "─┼─" + "─".repeat(descWidth) + "─┼─" + "─".repeat(tagsWidth)));
|
|
230776
230960
|
results.forEach((tool) => {
|
|
230777
|
-
const
|
|
230961
|
+
const nameText = tool.name.length > nameWidth ? tool.name.substring(0, nameWidth - 3) + "..." : tool.name.padEnd(nameWidth);
|
|
230962
|
+
const statusText = tool.verified ? "✓ Verified" : "✗ Unverified";
|
|
230963
|
+
const statusColor = tool.verified ? import_picocolors13.default.green : import_picocolors13.default.yellow;
|
|
230964
|
+
const status = statusColor(statusText.padEnd(statusWidth));
|
|
230778
230965
|
const desc = tool.description.length > descWidth ? tool.description.substring(0, descWidth - 3) + "..." : tool.description.padEnd(descWidth);
|
|
230779
230966
|
const tags = (tool.tags || []).join(", ");
|
|
230780
230967
|
const tagsDisplay = tags.length > tagsWidth ? tags.substring(0, tagsWidth - 3) + "..." : tags.padEnd(tagsWidth);
|
|
230781
|
-
console.error(import_picocolors13.default.
|
|
230968
|
+
console.error(import_picocolors13.default.cyan(nameText) + import_picocolors13.default.gray(" │ ") + status + import_picocolors13.default.gray(" │ ") + import_picocolors13.default.white(desc) + import_picocolors13.default.gray(" │ ") + import_picocolors13.default.magenta(tagsDisplay));
|
|
230782
230969
|
});
|
|
230783
|
-
console.error("═".repeat(
|
|
230970
|
+
console.error(import_picocolors13.default.gray("═".repeat(totalWidth)));
|
|
230784
230971
|
console.error(import_picocolors13.default.dim(`Total: ${results.length} tool${results.length === 1 ? "" : "s"}`));
|
|
230785
230972
|
}
|
|
230786
230973
|
function displayResultsList(results) {
|
|
@@ -230788,10 +230975,12 @@ function displayResultsList(results) {
|
|
|
230788
230975
|
` + import_picocolors13.default.bold("Search Results:"));
|
|
230789
230976
|
console.error("");
|
|
230790
230977
|
results.forEach((tool, index) => {
|
|
230791
|
-
|
|
230792
|
-
|
|
230978
|
+
const statusIndicator = tool.verified ? import_picocolors13.default.green("✓") : import_picocolors13.default.yellow("✗");
|
|
230979
|
+
const statusText = tool.verified ? import_picocolors13.default.green("verified") : import_picocolors13.default.red("unverified");
|
|
230980
|
+
console.error(`${import_picocolors13.default.cyan(`${index + 1}.`)} ${import_picocolors13.default.cyan(tool.name)} ${statusIndicator} ${import_picocolors13.default.dim(`(${statusText})`)}`);
|
|
230981
|
+
console.error(` ${import_picocolors13.default.white(tool.description)}`);
|
|
230793
230982
|
if (tool.tags && tool.tags.length > 0) {
|
|
230794
|
-
console.error(` ${import_picocolors13.default.
|
|
230983
|
+
console.error(` ${import_picocolors13.default.dim("Tags:")} ${import_picocolors13.default.magenta(tool.tags.join(", "))}`);
|
|
230795
230984
|
}
|
|
230796
230985
|
console.error("");
|
|
230797
230986
|
});
|
|
@@ -231154,6 +231343,9 @@ var { values, positionals } = parseArgs({
|
|
|
231154
231343
|
},
|
|
231155
231344
|
mount: {
|
|
231156
231345
|
type: "string"
|
|
231346
|
+
},
|
|
231347
|
+
tool: {
|
|
231348
|
+
type: "string"
|
|
231157
231349
|
}
|
|
231158
231350
|
},
|
|
231159
231351
|
allowPositionals: true,
|
|
@@ -231228,6 +231420,12 @@ async function main() {
|
|
|
231228
231420
|
mount: values.mount
|
|
231229
231421
|
});
|
|
231230
231422
|
break;
|
|
231423
|
+
case "sign":
|
|
231424
|
+
await handleSignToolCommand(commandArgs, {
|
|
231425
|
+
help: values.help,
|
|
231426
|
+
tool: values.tool
|
|
231427
|
+
});
|
|
231428
|
+
break;
|
|
231231
231429
|
case "get":
|
|
231232
231430
|
await handleCoreGetCommand(commandArgs, {
|
|
231233
231431
|
help: values.help,
|
|
@@ -231268,6 +231466,7 @@ async function main() {
|
|
|
231268
231466
|
{ value: "publish", label: "\uD83D\uDCE4 Publish a tool" },
|
|
231269
231467
|
{ value: "init", label: "\uD83D\uDCDD Create a new tool definition" },
|
|
231270
231468
|
{ value: "env", label: "\uD83C\uDF0D Manage environment variables" },
|
|
231469
|
+
{ value: "sign", label: "✍️ Sign a tool definition" },
|
|
231271
231470
|
{ value: "config", label: "\uD83D\uDD27 Configure Enact settings" },
|
|
231272
231471
|
{ value: "auth", label: "\uD83D\uDD10 Manage authentication" },
|
|
231273
231472
|
{ value: "remote", label: "\uD83C\uDF10 Manage remote servers" },
|
|
@@ -231316,6 +231515,9 @@ async function main() {
|
|
|
231316
231515
|
}
|
|
231317
231516
|
return;
|
|
231318
231517
|
}
|
|
231518
|
+
if (action === "sign") {
|
|
231519
|
+
await handleSignToolCommand([], {});
|
|
231520
|
+
}
|
|
231319
231521
|
if (action === "auth") {
|
|
231320
231522
|
const authAction = await ve({
|
|
231321
231523
|
message: "Authentication:",
|
package/dist/index.js.bak
CHANGED
|
@@ -214774,6 +214774,13 @@ class EnactApiClient {
|
|
|
214774
214774
|
throw new EnactApiError("Unknown error occurred", 0);
|
|
214775
214775
|
}
|
|
214776
214776
|
}
|
|
214777
|
+
async signTool(toolId, payload, token, tokenType = "cli") {
|
|
214778
|
+
const endpoint = `/functions/v1/tools/${encodeURIComponent(toolId)}/signatures`;
|
|
214779
|
+
return this.makeRequest(endpoint, {
|
|
214780
|
+
method: "POST",
|
|
214781
|
+
body: JSON.stringify(payload)
|
|
214782
|
+
}, token, tokenType);
|
|
214783
|
+
}
|
|
214777
214784
|
generateOAuthUrl(options) {
|
|
214778
214785
|
const params = new URLSearchParams({
|
|
214779
214786
|
response_type: "code",
|
|
@@ -229705,6 +229712,33 @@ class EnactCore {
|
|
|
229705
229712
|
};
|
|
229706
229713
|
}
|
|
229707
229714
|
}
|
|
229715
|
+
static async checkToolVerificationStatus(tool) {
|
|
229716
|
+
const documentForVerification = {
|
|
229717
|
+
command: tool.command,
|
|
229718
|
+
description: tool.description,
|
|
229719
|
+
from: tool.from,
|
|
229720
|
+
name: tool.name,
|
|
229721
|
+
signatures: tool.signatures?.map((sig) => ({
|
|
229722
|
+
signature: sig.value,
|
|
229723
|
+
publicKey: "",
|
|
229724
|
+
algorithm: sig.algorithm,
|
|
229725
|
+
timestamp: new Date(sig.created).getTime()
|
|
229726
|
+
}))
|
|
229727
|
+
};
|
|
229728
|
+
let isValid = false;
|
|
229729
|
+
if (tool.signatures && tool.signatures.length > 0) {
|
|
229730
|
+
isValid = tool.signatures.some((sig) => {
|
|
229731
|
+
const referenceSignature = {
|
|
229732
|
+
signature: sig.value,
|
|
229733
|
+
publicKey: "",
|
|
229734
|
+
algorithm: sig.algorithm,
|
|
229735
|
+
timestamp: new Date(sig.created).getTime()
|
|
229736
|
+
};
|
|
229737
|
+
return SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ["command", "description", "from", "name"] });
|
|
229738
|
+
});
|
|
229739
|
+
}
|
|
229740
|
+
return isValid;
|
|
229741
|
+
}
|
|
229708
229742
|
async verifyTool(tool, dangerouslySkipVerification = false) {
|
|
229709
229743
|
if (dangerouslySkipVerification) {
|
|
229710
229744
|
logger_default.warn(`Skipping signature verification for tool: ${tool.name}`);
|
|
@@ -229714,23 +229748,8 @@ class EnactCore {
|
|
|
229714
229748
|
if (!tool.signatures || tool.signatures.length === 0) {
|
|
229715
229749
|
throw new Error(`Tool ${tool.name} does not have any signatures`);
|
|
229716
229750
|
}
|
|
229717
|
-
const
|
|
229718
|
-
|
|
229719
|
-
description: tool.description,
|
|
229720
|
-
from: tool.from,
|
|
229721
|
-
name: tool.name
|
|
229722
|
-
};
|
|
229723
|
-
const referenceSignature = {
|
|
229724
|
-
signature: tool.signatures[0].value,
|
|
229725
|
-
publicKey: "",
|
|
229726
|
-
algorithm: tool.signatures[0].algorithm,
|
|
229727
|
-
timestamp: new Date(tool.signatures[0].created).getTime()
|
|
229728
|
-
};
|
|
229729
|
-
const canonicalDoc = SigningService.getCanonicalDocument(documentForVerification, { includeFields: ["command", "description", "from", "name"] });
|
|
229730
|
-
const docString = JSON.stringify(canonicalDoc);
|
|
229731
|
-
const messageHash = CryptoUtils.hash(docString);
|
|
229732
|
-
const directVerify = CryptoUtils.verify(referenceSignature.publicKey, messageHash, referenceSignature.signature);
|
|
229733
|
-
const isValid = SigningService.verifyDocument(documentForVerification, referenceSignature, { includeFields: ["command", "description", "from", "name"] });
|
|
229751
|
+
const isValid = await EnactCore.checkToolVerificationStatus(tool);
|
|
229752
|
+
console.log("Final verification result:", isValid);
|
|
229734
229753
|
if (!isValid) {
|
|
229735
229754
|
throw new Error(`Tool ${tool.name} has invalid signatures`);
|
|
229736
229755
|
}
|
|
@@ -230084,9 +230103,11 @@ ${import_picocolors13.default.bold("EXAMPLES:")}
|
|
|
230084
230103
|
try {
|
|
230085
230104
|
const tool = await apiClient.getTool(result.name);
|
|
230086
230105
|
if (tool) {
|
|
230106
|
+
const isValid = await EnactCore.checkToolVerificationStatus(tool);
|
|
230087
230107
|
const enactTool = {
|
|
230088
230108
|
name: tool.name,
|
|
230089
230109
|
description: tool.description || "",
|
|
230110
|
+
verified: isValid,
|
|
230090
230111
|
command: tool.command,
|
|
230091
230112
|
from: tool.from,
|
|
230092
230113
|
version: tool.version || "1.0.0",
|
|
@@ -230268,6 +230289,159 @@ async function collectParametersInteractively(inputSchema) {
|
|
|
230268
230289
|
}
|
|
230269
230290
|
return params;
|
|
230270
230291
|
}
|
|
230292
|
+
async function handleSignToolCommand(args, options) {
|
|
230293
|
+
if (options.help) {
|
|
230294
|
+
console.error(`
|
|
230295
|
+
Usage: enact sign [options]
|
|
230296
|
+
Sign a tool definition using your private key
|
|
230297
|
+
Options:
|
|
230298
|
+
--help, -h Show this help message
|
|
230299
|
+
--tool query Search for the tool to sign (name)
|
|
230300
|
+
Examples:
|
|
230301
|
+
enact sign --tool myorg/mytool
|
|
230302
|
+
`);
|
|
230303
|
+
return;
|
|
230304
|
+
}
|
|
230305
|
+
if (!options.tool) {
|
|
230306
|
+
const inputSchema = {
|
|
230307
|
+
type: "object",
|
|
230308
|
+
properties: {
|
|
230309
|
+
toolName: {
|
|
230310
|
+
type: "string",
|
|
230311
|
+
description: "The name of the tool to run"
|
|
230312
|
+
}
|
|
230313
|
+
},
|
|
230314
|
+
required: ["tool"]
|
|
230315
|
+
};
|
|
230316
|
+
const params = await collectParametersInteractively(inputSchema);
|
|
230317
|
+
options.tool = params.toolName;
|
|
230318
|
+
}
|
|
230319
|
+
const spinner = Y2();
|
|
230320
|
+
spinner.start("Searching for tools...");
|
|
230321
|
+
const results = [];
|
|
230322
|
+
try {
|
|
230323
|
+
const searchOptions = {
|
|
230324
|
+
query: options.tool ? options.tool : "",
|
|
230325
|
+
limit: 20,
|
|
230326
|
+
tags: undefined,
|
|
230327
|
+
author: undefined,
|
|
230328
|
+
format: "table"
|
|
230329
|
+
};
|
|
230330
|
+
const apiClient = await EnactApiClient.create();
|
|
230331
|
+
const searchResults = await apiClient.searchTools(searchOptions);
|
|
230332
|
+
for (const result of searchResults) {
|
|
230333
|
+
if (result.name) {
|
|
230334
|
+
try {
|
|
230335
|
+
const tool = await apiClient.getTool(result.name);
|
|
230336
|
+
if (tool) {
|
|
230337
|
+
const documentForVerification2 = {
|
|
230338
|
+
command: tool.command,
|
|
230339
|
+
description: tool.description,
|
|
230340
|
+
from: tool.from,
|
|
230341
|
+
name: tool.name
|
|
230342
|
+
};
|
|
230343
|
+
const isValid = await EnactCore.checkToolVerificationStatus(tool);
|
|
230344
|
+
const enactTool = {
|
|
230345
|
+
name: tool.name,
|
|
230346
|
+
description: tool.description || "",
|
|
230347
|
+
verified: isValid,
|
|
230348
|
+
command: tool.command,
|
|
230349
|
+
from: tool.from,
|
|
230350
|
+
version: tool.version || "1.0.0",
|
|
230351
|
+
timeout: tool.timeout,
|
|
230352
|
+
tags: tool.tags || [],
|
|
230353
|
+
inputSchema: tool.inputSchema,
|
|
230354
|
+
outputSchema: tool.outputSchema,
|
|
230355
|
+
env: tool.env_vars ? Object.fromEntries(Object.entries(tool.env_vars).map(([key, config2]) => [
|
|
230356
|
+
key,
|
|
230357
|
+
{ ...config2, source: config2.source || "env" }
|
|
230358
|
+
])) : undefined,
|
|
230359
|
+
signature: tool.signature,
|
|
230360
|
+
signatures: Array.isArray(tool.signatures) ? tool.signatures : tool.signatures ? Object.values(tool.signatures) : undefined,
|
|
230361
|
+
namespace: tool.namespace,
|
|
230362
|
+
resources: tool.resources,
|
|
230363
|
+
license: tool.license,
|
|
230364
|
+
authors: tool.authors,
|
|
230365
|
+
examples: tool.examples,
|
|
230366
|
+
annotations: tool.annotations
|
|
230367
|
+
};
|
|
230368
|
+
results.push(enactTool);
|
|
230369
|
+
}
|
|
230370
|
+
} catch (error2) {
|
|
230371
|
+
continue;
|
|
230372
|
+
}
|
|
230373
|
+
}
|
|
230374
|
+
}
|
|
230375
|
+
spinner.stop(`Found ${results.length} tool${results.length === 1 ? "" : "s"}`);
|
|
230376
|
+
if (results.length === 0) {
|
|
230377
|
+
Me("No tools found matching your criteria.", "No Results");
|
|
230378
|
+
Me(`Try:
|
|
230379
|
+
• Broader keywords
|
|
230380
|
+
• Removing filters
|
|
230381
|
+
• Different spelling`, "Suggestions");
|
|
230382
|
+
return;
|
|
230383
|
+
}
|
|
230384
|
+
} catch (error2) {
|
|
230385
|
+
spinner.stop("Search failed");
|
|
230386
|
+
if (error2.message?.includes("ENOTFOUND") || error2.message?.includes("ECONNREFUSED")) {
|
|
230387
|
+
Me("Could not connect to the Enact registry. Check your internet connection.", "Connection Error");
|
|
230388
|
+
} else {
|
|
230389
|
+
Me(error2 instanceof Error ? error2.message : String(error2), "Error");
|
|
230390
|
+
}
|
|
230391
|
+
console.error(import_picocolors13.default.red(`Search failed: ${error2 instanceof Error ? error2.message : String(error2)}`));
|
|
230392
|
+
process.exit(1);
|
|
230393
|
+
}
|
|
230394
|
+
const selected_tool = await ve({
|
|
230395
|
+
message: "Select a tool to sign:",
|
|
230396
|
+
options: results.map((tool) => ({
|
|
230397
|
+
value: tool,
|
|
230398
|
+
label: `${tool.name} - ${tool.description.substring(0, 60)}${tool.description.length > 60 ? "..." : ""} - Verified: ${tool.verified ? import_picocolors13.default.green("Yes") : import_picocolors13.default.red("No")}`
|
|
230399
|
+
}))
|
|
230400
|
+
});
|
|
230401
|
+
const documentForVerification = {
|
|
230402
|
+
command: selected_tool.command,
|
|
230403
|
+
description: selected_tool.description,
|
|
230404
|
+
from: selected_tool.from,
|
|
230405
|
+
name: selected_tool.name
|
|
230406
|
+
};
|
|
230407
|
+
const privateKeys = await KeyManager.getAllPrivateKeys();
|
|
230408
|
+
const privateKey = await ve({
|
|
230409
|
+
message: "Select a private key to sign with:",
|
|
230410
|
+
options: privateKeys.map((key) => ({
|
|
230411
|
+
value: key,
|
|
230412
|
+
label: `${key.fileName}`
|
|
230413
|
+
}))
|
|
230414
|
+
});
|
|
230415
|
+
const TrustedKey = CryptoUtils.getPublicKeyFromPrivate(privateKey.key);
|
|
230416
|
+
if (selected_tool.signatures && selected_tool.signatures.length > 0) {
|
|
230417
|
+
const alreadySigned = selected_tool.signatures.some((sig) => {
|
|
230418
|
+
const referenceSignature = {
|
|
230419
|
+
signature: sig.value,
|
|
230420
|
+
publicKey: "",
|
|
230421
|
+
algorithm: sig.algorithm,
|
|
230422
|
+
timestamp: new Date(sig.created).getTime()
|
|
230423
|
+
};
|
|
230424
|
+
return SigningService.verifyDocumentWithPublicKey(documentForVerification, referenceSignature, TrustedKey, { includeFields: ["command", "description", "from", "name"] });
|
|
230425
|
+
});
|
|
230426
|
+
if (alreadySigned) {
|
|
230427
|
+
console.log(import_picocolors13.default.green("✓ Tool has already been signed with the selected key."));
|
|
230428
|
+
return;
|
|
230429
|
+
}
|
|
230430
|
+
}
|
|
230431
|
+
const spinnerSign = Y2();
|
|
230432
|
+
console.error(spinnerSign.start("Signing tool..."));
|
|
230433
|
+
const signature = await SigningService.signDocument(documentForVerification, privateKey.key, { includeFields: ["command", "description", "from", "name"] });
|
|
230434
|
+
spinnerSign.stop(import_picocolors13.default.green("✓ Tool signed successfully"));
|
|
230435
|
+
console.error(import_picocolors13.default.cyan(`
|
|
230436
|
+
Signature Details:`));
|
|
230437
|
+
console.error(import_picocolors13.default.cyan(` Signature: ${signature.signature}`));
|
|
230438
|
+
console.error(import_picocolors13.default.cyan(` Algorithm: ${signature.algorithm}`));
|
|
230439
|
+
console.error(import_picocolors13.default.cyan(` Created: ${new Date(signature.timestamp).toISOString()}`));
|
|
230440
|
+
console.error(import_picocolors13.default.cyan(` Public Key: ${TrustedKey}`));
|
|
230441
|
+
console.error(import_picocolors13.default.red(`
|
|
230442
|
+
Pushing the signature to the registry is not yet implemented.`));
|
|
230443
|
+
return signature;
|
|
230444
|
+
}
|
|
230271
230445
|
async function handleCoreExecCommand(args, options) {
|
|
230272
230446
|
if (options.help) {
|
|
230273
230447
|
console.error(`
|
|
@@ -230509,6 +230683,7 @@ Environment variables:`));
|
|
|
230509
230683
|
const enactTool = {
|
|
230510
230684
|
name: toolDefinition.name,
|
|
230511
230685
|
description: toolDefinition.description || "",
|
|
230686
|
+
verified: true,
|
|
230512
230687
|
command: toolDefinition.command,
|
|
230513
230688
|
from: toolDefinition.from,
|
|
230514
230689
|
version: toolDefinition.version || "1.0.0",
|
|
@@ -230675,9 +230850,11 @@ ${import_picocolors13.default.bold("EXAMPLES:")}
|
|
|
230675
230850
|
Se(import_picocolors13.default.red(`Tool not found: ${toolName}`));
|
|
230676
230851
|
process.exit(1);
|
|
230677
230852
|
}
|
|
230853
|
+
const isValid = EnactCore.checkToolVerificationStatus(toolDefinition);
|
|
230678
230854
|
const tool = {
|
|
230679
230855
|
name: toolDefinition.name,
|
|
230680
230856
|
description: toolDefinition.description || "",
|
|
230857
|
+
verified: isValid,
|
|
230681
230858
|
command: toolDefinition.command,
|
|
230682
230859
|
from: toolDefinition.from,
|
|
230683
230860
|
version: toolDefinition.version || "1.0.0",
|
|
@@ -230716,6 +230893,11 @@ ${import_picocolors13.default.bold(import_picocolors13.default.cyan(`\uD83D\uDCE
|
|
|
230716
230893
|
if (tool.command) {
|
|
230717
230894
|
console.error(`${import_picocolors13.default.bold("Command:")} ${import_picocolors13.default.gray(tool.command)}`);
|
|
230718
230895
|
}
|
|
230896
|
+
if (tool.verified) {
|
|
230897
|
+
console.error(`${import_picocolors13.default.bold("Verification:")} ${import_picocolors13.default.green("Verified ✓")}`);
|
|
230898
|
+
} else {
|
|
230899
|
+
console.error(`${import_picocolors13.default.bold("Verification:")} ${import_picocolors13.default.red("Unverified ✗")}`);
|
|
230900
|
+
}
|
|
230719
230901
|
if (tool.from) {
|
|
230720
230902
|
console.error(`${import_picocolors13.default.bold("Container:")} ${import_picocolors13.default.gray(tool.from)}`);
|
|
230721
230903
|
}
|
|
@@ -230766,20 +230948,25 @@ ${import_picocolors13.default.bold("Examples:")}`);
|
|
|
230766
230948
|
function displayResultsTable(results) {
|
|
230767
230949
|
console.error(`
|
|
230768
230950
|
` + import_picocolors13.default.bold("Search Results:"));
|
|
230769
|
-
console.error("═".repeat(100));
|
|
230770
230951
|
const nameWidth = 40;
|
|
230952
|
+
const statusWidth = 15;
|
|
230771
230953
|
const descWidth = 45;
|
|
230772
230954
|
const tagsWidth = 20;
|
|
230773
|
-
|
|
230774
|
-
console.error(
|
|
230955
|
+
const totalWidth = nameWidth + statusWidth + descWidth + tagsWidth + 9;
|
|
230956
|
+
console.error(import_picocolors13.default.gray("═".repeat(totalWidth)));
|
|
230957
|
+
console.error(import_picocolors13.default.bold(import_picocolors13.default.white("NAME".padEnd(nameWidth))) + import_picocolors13.default.gray(" │ ") + import_picocolors13.default.bold(import_picocolors13.default.white("STATUS".padEnd(statusWidth))) + import_picocolors13.default.gray(" │ ") + import_picocolors13.default.bold(import_picocolors13.default.white("DESCRIPTION".padEnd(descWidth))) + import_picocolors13.default.gray(" │ ") + import_picocolors13.default.bold(import_picocolors13.default.white("TAGS".padEnd(tagsWidth))));
|
|
230958
|
+
console.error(import_picocolors13.default.gray("─".repeat(nameWidth) + "─┼─" + "─".repeat(statusWidth) + "─┼─" + "─".repeat(descWidth) + "─┼─" + "─".repeat(tagsWidth)));
|
|
230775
230959
|
results.forEach((tool) => {
|
|
230776
|
-
const
|
|
230960
|
+
const nameText = tool.name.length > nameWidth ? tool.name.substring(0, nameWidth - 3) + "..." : tool.name.padEnd(nameWidth);
|
|
230961
|
+
const statusText = tool.verified ? "✓ Verified" : "✗ Unverified";
|
|
230962
|
+
const statusColor = tool.verified ? import_picocolors13.default.green : import_picocolors13.default.yellow;
|
|
230963
|
+
const status = statusColor(statusText.padEnd(statusWidth));
|
|
230777
230964
|
const desc = tool.description.length > descWidth ? tool.description.substring(0, descWidth - 3) + "..." : tool.description.padEnd(descWidth);
|
|
230778
230965
|
const tags = (tool.tags || []).join(", ");
|
|
230779
230966
|
const tagsDisplay = tags.length > tagsWidth ? tags.substring(0, tagsWidth - 3) + "..." : tags.padEnd(tagsWidth);
|
|
230780
|
-
console.error(import_picocolors13.default.
|
|
230967
|
+
console.error(import_picocolors13.default.cyan(nameText) + import_picocolors13.default.gray(" │ ") + status + import_picocolors13.default.gray(" │ ") + import_picocolors13.default.white(desc) + import_picocolors13.default.gray(" │ ") + import_picocolors13.default.magenta(tagsDisplay));
|
|
230781
230968
|
});
|
|
230782
|
-
console.error("═".repeat(
|
|
230969
|
+
console.error(import_picocolors13.default.gray("═".repeat(totalWidth)));
|
|
230783
230970
|
console.error(import_picocolors13.default.dim(`Total: ${results.length} tool${results.length === 1 ? "" : "s"}`));
|
|
230784
230971
|
}
|
|
230785
230972
|
function displayResultsList(results) {
|
|
@@ -230787,10 +230974,12 @@ function displayResultsList(results) {
|
|
|
230787
230974
|
` + import_picocolors13.default.bold("Search Results:"));
|
|
230788
230975
|
console.error("");
|
|
230789
230976
|
results.forEach((tool, index) => {
|
|
230790
|
-
|
|
230791
|
-
|
|
230977
|
+
const statusIndicator = tool.verified ? import_picocolors13.default.green("✓") : import_picocolors13.default.yellow("✗");
|
|
230978
|
+
const statusText = tool.verified ? import_picocolors13.default.green("verified") : import_picocolors13.default.red("unverified");
|
|
230979
|
+
console.error(`${import_picocolors13.default.cyan(`${index + 1}.`)} ${import_picocolors13.default.cyan(tool.name)} ${statusIndicator} ${import_picocolors13.default.dim(`(${statusText})`)}`);
|
|
230980
|
+
console.error(` ${import_picocolors13.default.white(tool.description)}`);
|
|
230792
230981
|
if (tool.tags && tool.tags.length > 0) {
|
|
230793
|
-
console.error(` ${import_picocolors13.default.
|
|
230982
|
+
console.error(` ${import_picocolors13.default.dim("Tags:")} ${import_picocolors13.default.magenta(tool.tags.join(", "))}`);
|
|
230794
230983
|
}
|
|
230795
230984
|
console.error("");
|
|
230796
230985
|
});
|
|
@@ -231153,6 +231342,9 @@ var { values, positionals } = parseArgs({
|
|
|
231153
231342
|
},
|
|
231154
231343
|
mount: {
|
|
231155
231344
|
type: "string"
|
|
231345
|
+
},
|
|
231346
|
+
tool: {
|
|
231347
|
+
type: "string"
|
|
231156
231348
|
}
|
|
231157
231349
|
},
|
|
231158
231350
|
allowPositionals: true,
|
|
@@ -231227,6 +231419,12 @@ async function main() {
|
|
|
231227
231419
|
mount: values.mount
|
|
231228
231420
|
});
|
|
231229
231421
|
break;
|
|
231422
|
+
case "sign":
|
|
231423
|
+
await handleSignToolCommand(commandArgs, {
|
|
231424
|
+
help: values.help,
|
|
231425
|
+
tool: values.tool
|
|
231426
|
+
});
|
|
231427
|
+
break;
|
|
231230
231428
|
case "get":
|
|
231231
231429
|
await handleCoreGetCommand(commandArgs, {
|
|
231232
231430
|
help: values.help,
|
|
@@ -231267,6 +231465,7 @@ async function main() {
|
|
|
231267
231465
|
{ value: "publish", label: "\uD83D\uDCE4 Publish a tool" },
|
|
231268
231466
|
{ value: "init", label: "\uD83D\uDCDD Create a new tool definition" },
|
|
231269
231467
|
{ value: "env", label: "\uD83C\uDF0D Manage environment variables" },
|
|
231468
|
+
{ value: "sign", label: "✍️ Sign a tool definition" },
|
|
231270
231469
|
{ value: "config", label: "\uD83D\uDD27 Configure Enact settings" },
|
|
231271
231470
|
{ value: "auth", label: "\uD83D\uDD10 Manage authentication" },
|
|
231272
231471
|
{ value: "remote", label: "\uD83C\uDF10 Manage remote servers" },
|
|
@@ -231315,6 +231514,9 @@ async function main() {
|
|
|
231315
231514
|
}
|
|
231316
231515
|
return;
|
|
231317
231516
|
}
|
|
231517
|
+
if (action === "sign") {
|
|
231518
|
+
await handleSignToolCommand([], {});
|
|
231519
|
+
}
|
|
231318
231520
|
if (action === "auth") {
|
|
231319
231521
|
const authAction = await ve({
|
|
231320
231522
|
message: "Authentication:",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enactprotocol/cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.13",
|
|
4
4
|
"description": "Official CLI for the Enact Protocol - package, secure, and discover AI tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"node": ">=18.0.0"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@enactprotocol/shared": "1.2.
|
|
45
|
+
"@enactprotocol/shared": "1.2.13",
|
|
46
46
|
"@clack/core": "^0.4.2",
|
|
47
47
|
"@clack/prompts": "^0.10.1",
|
|
48
48
|
"picocolors": "^1.1.1"
|