@ametyst/cli 0.3.6 → 0.3.7
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 +167 -11
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -112026,6 +112026,7 @@ var init_core = __esm({
|
|
|
112026
112026
|
var grant_keystore_exports = {};
|
|
112027
112027
|
__export(grant_keystore_exports, {
|
|
112028
112028
|
GRANT_ENTRY_FORMAT: () => GRANT_ENTRY_FORMAT,
|
|
112029
|
+
MissingGrantKeyError: () => MissingGrantKeyError,
|
|
112029
112030
|
buildGrantVault: () => buildGrantVault,
|
|
112030
112031
|
createGrantKeyIssuer: () => createGrantKeyIssuer,
|
|
112031
112032
|
deleteGrantEntry: () => deleteGrantEntry,
|
|
@@ -112033,6 +112034,8 @@ __export(grant_keystore_exports, {
|
|
|
112033
112034
|
generateGrantKey: () => generateGrantKey,
|
|
112034
112035
|
grantEntryPath: () => grantEntryPath,
|
|
112035
112036
|
grantsDir: () => grantsDir,
|
|
112037
|
+
hasGrantSigningKey: () => hasGrantSigningKey,
|
|
112038
|
+
isMissingGrantKeyError: () => isMissingGrantKeyError,
|
|
112036
112039
|
listGrantAddresses: () => listGrantAddresses,
|
|
112037
112040
|
listGrantEntries: () => listGrantEntries,
|
|
112038
112041
|
missingGrantKeyMessage: () => missingGrantKeyMessage,
|
|
@@ -112180,6 +112183,19 @@ function deleteGrantEntry(address, dir) {
|
|
|
112180
112183
|
function missingGrantKeyMessage(address) {
|
|
112181
112184
|
return `no local key for grant address ${address} \u2014 this machine cannot sign for that grant. Run requestAccess again to mint a fresh session key and have your admin approve it.`;
|
|
112182
112185
|
}
|
|
112186
|
+
function isMissingGrantKeyError(err) {
|
|
112187
|
+
return err instanceof MissingGrantKeyError;
|
|
112188
|
+
}
|
|
112189
|
+
function hasGrantSigningKey(params) {
|
|
112190
|
+
let address;
|
|
112191
|
+
try {
|
|
112192
|
+
address = normalizeGrantAddress(params.address);
|
|
112193
|
+
} catch {
|
|
112194
|
+
return false;
|
|
112195
|
+
}
|
|
112196
|
+
if (readGrantEntry(address, params.dir)) return true;
|
|
112197
|
+
return typeof params.vaultAddress === "string" && params.vaultAddress.toLowerCase() === address;
|
|
112198
|
+
}
|
|
112183
112199
|
function resolveGrantSigningKey(params) {
|
|
112184
112200
|
const address = normalizeGrantAddress(params.address);
|
|
112185
112201
|
const entry = readGrantEntry(address, params.dir);
|
|
@@ -112190,7 +112206,7 @@ function resolveGrantSigningKey(params) {
|
|
|
112190
112206
|
if (params.vaultJson && typeof vaultAddress === "string" && vaultAddress.toLowerCase() === address) {
|
|
112191
112207
|
return readVaultPrivateKey(params.vaultJson, params.passphrase);
|
|
112192
112208
|
}
|
|
112193
|
-
throw new
|
|
112209
|
+
throw new MissingGrantKeyError(address);
|
|
112194
112210
|
}
|
|
112195
112211
|
function createGrantKeyIssuer(options) {
|
|
112196
112212
|
return {
|
|
@@ -112214,7 +112230,7 @@ function createGrantKeyIssuer(options) {
|
|
|
112214
112230
|
}
|
|
112215
112231
|
};
|
|
112216
112232
|
}
|
|
112217
|
-
var GRANT_ENTRY_FORMAT, ADDRESS_RE2;
|
|
112233
|
+
var GRANT_ENTRY_FORMAT, ADDRESS_RE2, MissingGrantKeyError;
|
|
112218
112234
|
var init_grant_keystore = __esm({
|
|
112219
112235
|
"src/wallet/grant-keystore.ts"() {
|
|
112220
112236
|
"use strict";
|
|
@@ -112225,6 +112241,14 @@ var init_grant_keystore = __esm({
|
|
|
112225
112241
|
init_plaintext_vault();
|
|
112226
112242
|
GRANT_ENTRY_FORMAT = "grant-key-v1";
|
|
112227
112243
|
ADDRESS_RE2 = /^0x[0-9a-fA-F]{40}$/;
|
|
112244
|
+
MissingGrantKeyError = class extends Error {
|
|
112245
|
+
grantAddress;
|
|
112246
|
+
constructor(address) {
|
|
112247
|
+
super(missingGrantKeyMessage(address));
|
|
112248
|
+
this.name = "MissingGrantKeyError";
|
|
112249
|
+
this.grantAddress = address;
|
|
112250
|
+
}
|
|
112251
|
+
};
|
|
112228
112252
|
}
|
|
112229
112253
|
});
|
|
112230
112254
|
|
|
@@ -112412,7 +112436,7 @@ var init_version5 = __esm({
|
|
|
112412
112436
|
"src/version.ts"() {
|
|
112413
112437
|
"use strict";
|
|
112414
112438
|
init_esm_shims();
|
|
112415
|
-
CLI_VERSION = true ? "0.3.
|
|
112439
|
+
CLI_VERSION = true ? "0.3.7" : "0.0.0-dev";
|
|
112416
112440
|
}
|
|
112417
112441
|
});
|
|
112418
112442
|
|
|
@@ -115738,6 +115762,56 @@ function findCurrentApprovedWallet(wallets, eoaAddress, pendingWalletId) {
|
|
|
115738
115762
|
);
|
|
115739
115763
|
}
|
|
115740
115764
|
|
|
115765
|
+
// src/mcp-server/signer-binding.ts
|
|
115766
|
+
init_esm_shims();
|
|
115767
|
+
var BINDING_DERIVED_KEYS = [
|
|
115768
|
+
"virtualWalletKernelAccountClient",
|
|
115769
|
+
"permissionPlugin",
|
|
115770
|
+
"kernelDomain",
|
|
115771
|
+
"policyPrecheckPassed"
|
|
115772
|
+
];
|
|
115773
|
+
function nonEmpty(value2) {
|
|
115774
|
+
return typeof value2 === "string" && value2.trim() !== "" ? value2 : void 0;
|
|
115775
|
+
}
|
|
115776
|
+
function sameAddress(a, b) {
|
|
115777
|
+
return String(a ?? "").toLowerCase() === String(b ?? "").toLowerCase();
|
|
115778
|
+
}
|
|
115779
|
+
function signerBindingMoved(state, row) {
|
|
115780
|
+
const rowId = row?.id != null ? String(row.id) : void 0;
|
|
115781
|
+
const rowAddress = nonEmpty(row?.address);
|
|
115782
|
+
if (state.virtualWalletId && rowId && state.virtualWalletId !== rowId) return true;
|
|
115783
|
+
if (state.signerAddress && rowAddress && !sameAddress(state.signerAddress, rowAddress)) return true;
|
|
115784
|
+
return false;
|
|
115785
|
+
}
|
|
115786
|
+
function bindSignerToGrantRow(state, row) {
|
|
115787
|
+
const changed = signerBindingMoved(state, row);
|
|
115788
|
+
if (changed) {
|
|
115789
|
+
for (const key of BINDING_DERIVED_KEYS) delete state[key];
|
|
115790
|
+
}
|
|
115791
|
+
const rowAddress = nonEmpty(row?.address);
|
|
115792
|
+
if (rowAddress) state.signerAddress = rowAddress;
|
|
115793
|
+
const rowWalletAddress = nonEmpty(row?.walletAddress) ?? nonEmpty(row?.kernelAccountAddress);
|
|
115794
|
+
const rowPaymentManagerAddress = nonEmpty(row?.paymentManagerAddress);
|
|
115795
|
+
const rowPolicyId = row?.policyAssociated != null ? String(row.policyAssociated) : void 0;
|
|
115796
|
+
const rowId = row?.id != null ? String(row.id) : void 0;
|
|
115797
|
+
if (changed) {
|
|
115798
|
+
state.walletAddress = rowWalletAddress;
|
|
115799
|
+
state.paymentManagerAddress = rowPaymentManagerAddress;
|
|
115800
|
+
state.policyId = rowPolicyId;
|
|
115801
|
+
state.policyOnchainPermissions = nonEmpty(row?.policyOnchainPermissions);
|
|
115802
|
+
} else {
|
|
115803
|
+
state.walletAddress = rowWalletAddress ?? state.walletAddress;
|
|
115804
|
+
state.paymentManagerAddress = rowPaymentManagerAddress ?? state.paymentManagerAddress;
|
|
115805
|
+
state.policyId = rowPolicyId ?? state.policyId;
|
|
115806
|
+
state.policyOnchainPermissions = nonEmpty(row?.policyOnchainPermissions) ?? state.policyOnchainPermissions;
|
|
115807
|
+
}
|
|
115808
|
+
if (rowId) state.virtualWalletId = rowId;
|
|
115809
|
+
if (row?.policyName != null) state.policyName = String(row.policyName);
|
|
115810
|
+
if (row?.policyValidUntil != null) state.policyValidUntil = BigInt(row.policyValidUntil);
|
|
115811
|
+
state.authorizationStatus = "approved";
|
|
115812
|
+
return { changed, signerAddress: state.signerAddress };
|
|
115813
|
+
}
|
|
115814
|
+
|
|
115741
115815
|
// src/mcp-server/start-session.ts
|
|
115742
115816
|
init_esm_shims();
|
|
115743
115817
|
init_dist();
|
|
@@ -116049,11 +116123,11 @@ function clearWalletScopedCredentials(target) {
|
|
|
116049
116123
|
delete target[key];
|
|
116050
116124
|
}
|
|
116051
116125
|
}
|
|
116052
|
-
function
|
|
116126
|
+
function sameAddress2(a, b) {
|
|
116053
116127
|
return String(a ?? "").toLowerCase() === String(b ?? "").toLowerCase();
|
|
116054
116128
|
}
|
|
116055
116129
|
function mergeStartSessionCredentials(target, patch, responseKey, options = {}) {
|
|
116056
|
-
const walletChanged = patch.eoaAddress !== void 0 && !
|
|
116130
|
+
const walletChanged = patch.eoaAddress !== void 0 && !sameAddress2(patch.eoaAddress, target.eoaAddress);
|
|
116057
116131
|
if (walletChanged || options.grantChanged) {
|
|
116058
116132
|
clearWalletScopedCredentials(target);
|
|
116059
116133
|
}
|
|
@@ -121919,6 +121993,49 @@ function signingKeyForAddress(address, passphrase) {
|
|
|
121919
121993
|
passphrase: passphrase ?? currentCredentials.passphrase
|
|
121920
121994
|
});
|
|
121921
121995
|
}
|
|
121996
|
+
async function refreshSignerBinding() {
|
|
121997
|
+
if (!currentCredentials.apiKey) return { changed: false, address: currentCredentials.signerAddress };
|
|
121998
|
+
let wallets;
|
|
121999
|
+
try {
|
|
122000
|
+
wallets = await fetchVirtualWalletsFromBackend(currentCredentials.apiKey, true);
|
|
122001
|
+
} catch (err) {
|
|
122002
|
+
console.error(
|
|
122003
|
+
`\u26A0\uFE0F [signer-binding] could not re-read the grants \u2014 signing with the cached binding (${currentCredentials.signerAddress ?? "none"}): ${err instanceof Error ? err.message : String(err)}`
|
|
122004
|
+
);
|
|
122005
|
+
wallets = walletsCache || [];
|
|
122006
|
+
}
|
|
122007
|
+
const row = currentCredentials.pendingWalletId ? findCurrentApprovedWallet(wallets, ownedSigningAddresses(), currentCredentials.pendingWalletId) : selectNewestApprovedWalletAmong(
|
|
122008
|
+
wallets,
|
|
122009
|
+
(Array.isArray(wallets) ? wallets : []).map((w) => w?.address)
|
|
122010
|
+
);
|
|
122011
|
+
if (!row) return { changed: false, address: currentCredentials.signerAddress };
|
|
122012
|
+
const previousSigner = currentCredentials.signerAddress;
|
|
122013
|
+
const { changed, signerAddress } = bindSignerToGrantRow(currentCredentials, row);
|
|
122014
|
+
if (changed) {
|
|
122015
|
+
console.error(
|
|
122016
|
+
`\u{1F501} [signer-binding] the active grant moved \u2014 signer ${previousSigner ?? "none"} -> ${signerAddress ?? "none"} (virtual wallet ${currentCredentials.virtualWalletId}, policy ${currentCredentials.policyId ?? "unknown"}). Dropping the signer state derived from the old grant.`
|
|
122017
|
+
);
|
|
122018
|
+
}
|
|
122019
|
+
return { changed, address: signerAddress };
|
|
122020
|
+
}
|
|
122021
|
+
async function resolveSignerForMaterialization(passphrase) {
|
|
122022
|
+
await refreshSignerBinding();
|
|
122023
|
+
const address = currentCredentials.signerAddress || currentCredentials.eoaAddress || "";
|
|
122024
|
+
if (!address) {
|
|
122025
|
+
throw new Error(
|
|
122026
|
+
"no signer address for this session \u2014 no approved grant and no install wallet. Run requestAccess first."
|
|
122027
|
+
);
|
|
122028
|
+
}
|
|
122029
|
+
return { address, privateKey: signingKeyForAddress(address, passphrase) };
|
|
122030
|
+
}
|
|
122031
|
+
function hasSigningKeyForAddress(address) {
|
|
122032
|
+
if (!address) return false;
|
|
122033
|
+
try {
|
|
122034
|
+
return hasGrantSigningKey({ address, vaultAddress: currentCredentials.eoaAddress });
|
|
122035
|
+
} catch {
|
|
122036
|
+
return false;
|
|
122037
|
+
}
|
|
122038
|
+
}
|
|
121922
122039
|
var plaintextVaultMode = false;
|
|
121923
122040
|
function refreshPlaintextVaultMode() {
|
|
121924
122041
|
const vault = currentCredentials.walletKeystoreJson;
|
|
@@ -122983,12 +123100,15 @@ async function initializeCredentials(walletKeystoreJson, eoaAddress, config) {
|
|
|
122983
123100
|
const wallets = walletsCache || [];
|
|
122984
123101
|
const approvedWallet = findCurrentApprovedWallet(
|
|
122985
123102
|
wallets,
|
|
122986
|
-
|
|
123103
|
+
ownedSigningAddresses(),
|
|
122987
123104
|
currentCredentials.pendingWalletId
|
|
122988
123105
|
);
|
|
122989
123106
|
if (approvedWallet) {
|
|
122990
123107
|
console.error("\u2705 Found approved wallet from backend \u2014 authorization data stored");
|
|
122991
123108
|
currentCredentials.authorizationStatus = "approved";
|
|
123109
|
+
if (typeof approvedWallet.address === "string" && approvedWallet.address.trim() !== "") {
|
|
123110
|
+
currentCredentials.signerAddress = approvedWallet.address;
|
|
123111
|
+
}
|
|
122992
123112
|
currentCredentials.virtualWalletStatus = approvedWallet.status;
|
|
122993
123113
|
currentCredentials.walletAddress = approvedWallet.walletAddress || approvedWallet.kernelAccountAddress;
|
|
122994
123114
|
currentCredentials.virtualWalletId = String(approvedWallet.id);
|
|
@@ -123035,10 +123155,9 @@ async function createKernelClientFromVault() {
|
|
|
123035
123155
|
throw new Error("No passphrase or keystore available");
|
|
123036
123156
|
}
|
|
123037
123157
|
if (!cliConfig) throw new Error("CLI config not initialized");
|
|
123038
|
-
|
|
123039
|
-
|
|
123040
|
-
);
|
|
123041
|
-
console.error(`${ts()} Wallet key loaded`);
|
|
123158
|
+
const signer = await resolveSignerForMaterialization();
|
|
123159
|
+
let privateKey = signer.privateKey;
|
|
123160
|
+
console.error(`${ts()} Wallet key loaded \u2014 signing as ${signer.address}`);
|
|
123042
123161
|
try {
|
|
123043
123162
|
const { virtualWalletsManagers: virtualWalletsManagers2, financialAccounts: financialAccounts2 } = await getSDK();
|
|
123044
123163
|
console.error(`${ts()} Fetching wallet data by API key...`);
|
|
@@ -123799,7 +123918,7 @@ server.tool(
|
|
|
123799
123918
|
server.tool(
|
|
123800
123919
|
{
|
|
123801
123920
|
name: "getWalletStatus",
|
|
123802
|
-
description: "Get wallet status: auth, balance, policy, allowlist, WHICH GRANT AND KEY THIS SESSION SIGNS WITH, WHICH WORKSPACE this server is acting in, and the last 10 transactions (amount, merchant, timestamp, status). `signerAddress` is the address of the approved grant this session signs with \u2014 since every access request now mints its OWN ephemeral session key, it is NOT the same as `eoaAddress` (the install wallet) except for a grant approved before rotation; `activeVirtualWalletId` / `activePolicyId` name that grant's row. `workspace` is `{companyName, employeeName}` \u2014 the Ametyst workspace every task, memory document and payment from this server lands in; both fields are null when the profile could not be read, which means UNKNOWN, never 'no workspace'. A transaction `amount` is a EUR display string like `\u20AC0.0126`, or the em dash `\u2014` when the row carries no usable amount (none recorded, or a value that is not a base-units integer) \u2014 `\u2014` means UNKNOWN, never zero. The unformatted base-units value is on `amountRaw`, which is null for exactly those rows.",
|
|
123921
|
+
description: "Get wallet status: auth, balance, policy, allowlist, WHICH GRANT AND KEY THIS SESSION SIGNS WITH, WHICH WORKSPACE this server is acting in, and the last 10 transactions (amount, merchant, timestamp, status). `signerAddress` is the address of the approved grant this session signs with \u2014 since every access request now mints its OWN ephemeral session key, it is NOT the same as `eoaAddress` (the install wallet) except for a grant approved before rotation; `activeVirtualWalletId` / `activePolicyId` name that grant's row, and `signerKeyPresent` says whether this machine still holds the private key for `signerAddress` \u2014 `false` means no spend can be signed until `requestAccess` mints a fresh session key and an admin approves it. `workspace` is `{companyName, employeeName}` \u2014 the Ametyst workspace every task, memory document and payment from this server lands in; both fields are null when the profile could not be read, which means UNKNOWN, never 'no workspace'. A transaction `amount` is a EUR display string like `\u20AC0.0126`, or the em dash `\u2014` when the row carries no usable amount (none recorded, or a value that is not a base-units integer) \u2014 `\u2014` means UNKNOWN, never zero. The unformatted base-units value is on `amountRaw`, which is null for exactly those rows.",
|
|
123803
123922
|
inputs: []
|
|
123804
123923
|
},
|
|
123805
123924
|
async () => {
|
|
@@ -123834,6 +123953,9 @@ server.tool(
|
|
|
123834
123953
|
const freshWallet = selectNewestApprovedWalletAmong(freshWallets, ownedSigningAddresses());
|
|
123835
123954
|
const freshWalletIsActiveGrant = String(freshWallet?.id) === String(currentCredentials.virtualWalletId);
|
|
123836
123955
|
if (freshWallet && freshWalletIsActiveGrant) {
|
|
123956
|
+
if (typeof freshWallet.address === "string" && freshWallet.address.trim() !== "") {
|
|
123957
|
+
currentCredentials.signerAddress = freshWallet.address;
|
|
123958
|
+
}
|
|
123837
123959
|
if (freshWallet.policyAssociated != null) {
|
|
123838
123960
|
currentCredentials.policyId = String(freshWallet.policyAssociated);
|
|
123839
123961
|
}
|
|
@@ -123860,6 +123982,16 @@ server.tool(
|
|
|
123860
123982
|
// "which key signed this" readable from a payload instead of from a
|
|
123861
123983
|
// nonce-key autopsy — the same lesson as `activeVirtualWalletId` below.
|
|
123862
123984
|
signerAddress: currentCredentials.signerAddress || currentCredentials.eoaAddress || null,
|
|
123985
|
+
// CAN THIS MACHINE ACTUALLY SIGN FOR THAT GRANT? A rotated grant is
|
|
123986
|
+
// signable only from the per-grant keystore entry minted with it, and a
|
|
123987
|
+
// machine that lost it (a re-install, a restored home, a grant approved
|
|
123988
|
+
// on another laptop) is bound to a signer it cannot produce. Presence
|
|
123989
|
+
// only — no decryption, so an encrypted vault with no cached passphrase
|
|
123990
|
+
// still reports `true` here and bounces at spend time on the passphrase,
|
|
123991
|
+
// which is a different and recoverable problem.
|
|
123992
|
+
signerKeyPresent: hasSigningKeyForAddress(
|
|
123993
|
+
currentCredentials.signerAddress || currentCredentials.eoaAddress
|
|
123994
|
+
),
|
|
123863
123995
|
walletAddress: currentCredentials.walletAddress || null,
|
|
123864
123996
|
kernelClientActive: !!currentCredentials.virtualWalletKernelAccountClient,
|
|
123865
123997
|
// WHICH GRANT THIS SESSION SIGNS WITH. The 2026-09-01 incident — three
|
|
@@ -125336,11 +125468,13 @@ server.tool(
|
|
|
125336
125468
|
};
|
|
125337
125469
|
}
|
|
125338
125470
|
touchWalletActivity();
|
|
125471
|
+
let missingSignerKey;
|
|
125339
125472
|
if (!currentCredentials.virtualWalletKernelAccountClient && currentCredentials.authorizationStatus === "approved" && isWalletUnlocked()) {
|
|
125340
125473
|
try {
|
|
125341
125474
|
console.error("\u{1F504} [spend] Auto-creating kernel client...");
|
|
125342
125475
|
await createKernelClientFromVault();
|
|
125343
125476
|
} catch (kcErr) {
|
|
125477
|
+
if (isMissingGrantKeyError(kcErr)) missingSignerKey = kcErr;
|
|
125344
125478
|
console.error("\u274C [spend] Auto kernel client creation failed:", kcErr instanceof Error ? kcErr.message : String(kcErr));
|
|
125345
125479
|
}
|
|
125346
125480
|
}
|
|
@@ -125396,6 +125530,28 @@ server.tool(
|
|
|
125396
125530
|
const apiKey = currentCredentials.apiKey;
|
|
125397
125531
|
if (!kernelClient || !apiKey) {
|
|
125398
125532
|
console.error("\u26A0\uFE0F [spend] Missing kernel client or API key in state");
|
|
125533
|
+
if (missingSignerKey) {
|
|
125534
|
+
logSpendTelemetryEarlyErr();
|
|
125535
|
+
return {
|
|
125536
|
+
content: [
|
|
125537
|
+
{
|
|
125538
|
+
type: "text",
|
|
125539
|
+
text: JSON.stringify({
|
|
125540
|
+
success: false,
|
|
125541
|
+
...disclosePayment(),
|
|
125542
|
+
// PRE-PAYMENT
|
|
125543
|
+
error: "signer_key_missing",
|
|
125544
|
+
detail: missingSignerKey.message,
|
|
125545
|
+
guidance: {
|
|
125546
|
+
say_to_user: "This machine can't sign for your approved access any more \u2014 the session key it was issued to isn't here. I need to request access again so a fresh key can be approved.",
|
|
125547
|
+
next_action: "Call getAvailablePolicies(), let the user pick a policy, then call requestAccess with it. Once the admin approves the new request, retry this spend.",
|
|
125548
|
+
stop: true
|
|
125549
|
+
}
|
|
125550
|
+
})
|
|
125551
|
+
}
|
|
125552
|
+
]
|
|
125553
|
+
};
|
|
125554
|
+
}
|
|
125399
125555
|
if (currentCredentials.authorizationStatus === "pending") {
|
|
125400
125556
|
logSpendTelemetryEarlyErr();
|
|
125401
125557
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ametyst/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Ametyst CLI — embedded MCP server, wallet ops, agent payments",
|
|
6
6
|
"type": "module",
|
|
@@ -90,10 +90,10 @@
|
|
|
90
90
|
"esbuild@>=0.27.3 <0.28.1": "0.28.1"
|
|
91
91
|
},
|
|
92
92
|
"optionalDependencies": {
|
|
93
|
-
"@ametyst/cli-darwin-arm64": "0.3.
|
|
94
|
-
"@ametyst/cli-darwin-x64": "0.3.
|
|
95
|
-
"@ametyst/cli-linux-x64-gnu": "0.3.
|
|
96
|
-
"@ametyst/cli-win32-x64-msvc": "0.3.
|
|
93
|
+
"@ametyst/cli-darwin-arm64": "0.3.7",
|
|
94
|
+
"@ametyst/cli-darwin-x64": "0.3.7",
|
|
95
|
+
"@ametyst/cli-linux-x64-gnu": "0.3.7",
|
|
96
|
+
"@ametyst/cli-win32-x64-msvc": "0.3.7"
|
|
97
97
|
},
|
|
98
98
|
"scripts": {
|
|
99
99
|
"build:native": "cd native && cargo build --release && napi build --release",
|