@sundaeswap/sprinkles 0.6.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -181
- package/dist/cjs/Sprinkle/__tests__/action-integration.test.js +590 -0
- package/dist/cjs/Sprinkle/__tests__/action-integration.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/action-registry.test.js +193 -0
- package/dist/cjs/Sprinkle/__tests__/action-registry.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/action-runner.test.js +304 -0
- package/dist/cjs/Sprinkle/__tests__/action-runner.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/builtin-actions.test.js +1110 -0
- package/dist/cjs/Sprinkle/__tests__/builtin-actions.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/cli-adapter.test.js +744 -0
- package/dist/cjs/Sprinkle/__tests__/cli-adapter.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js +15 -1
- package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/mcp-adapter.test.js +711 -0
- package/dist/cjs/Sprinkle/__tests__/mcp-adapter.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/native-script.test.js +390 -0
- package/dist/cjs/Sprinkle/__tests__/native-script.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/tui-helpers.test.js +334 -0
- package/dist/cjs/Sprinkle/__tests__/tui-helpers.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/utility-actions.test.js +367 -0
- package/dist/cjs/Sprinkle/__tests__/utility-actions.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/wallet-transaction-actions.test.js +749 -0
- package/dist/cjs/Sprinkle/__tests__/wallet-transaction-actions.test.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/addressbook-actions.js +164 -0
- package/dist/cjs/Sprinkle/actions/builtin/addressbook-actions.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/blaze-helper.js +61 -0
- package/dist/cjs/Sprinkle/actions/builtin/blaze-helper.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/index.js +174 -0
- package/dist/cjs/Sprinkle/actions/builtin/index.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/native-script.js +139 -0
- package/dist/cjs/Sprinkle/actions/builtin/native-script.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/profile-actions.js +202 -0
- package/dist/cjs/Sprinkle/actions/builtin/profile-actions.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/settings-actions.js +87 -0
- package/dist/cjs/Sprinkle/actions/builtin/settings-actions.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/transaction-actions.js +345 -0
- package/dist/cjs/Sprinkle/actions/builtin/transaction-actions.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/utility-actions.js +218 -0
- package/dist/cjs/Sprinkle/actions/builtin/utility-actions.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/builtin/wallet-actions.js +212 -0
- package/dist/cjs/Sprinkle/actions/builtin/wallet-actions.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/cli-adapter.js +390 -0
- package/dist/cjs/Sprinkle/actions/cli-adapter.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/index.js +139 -0
- package/dist/cjs/Sprinkle/actions/index.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/mcp-adapter.js +557 -0
- package/dist/cjs/Sprinkle/actions/mcp-adapter.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/registry.js +92 -0
- package/dist/cjs/Sprinkle/actions/registry.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/runner.js +190 -0
- package/dist/cjs/Sprinkle/actions/runner.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/tui-helpers.js +96 -0
- package/dist/cjs/Sprinkle/actions/tui-helpers.js.map +1 -0
- package/dist/cjs/Sprinkle/actions/types.js +68 -0
- package/dist/cjs/Sprinkle/actions/types.js.map +1 -0
- package/dist/cjs/Sprinkle/index.js +678 -5
- package/dist/cjs/Sprinkle/index.js.map +1 -1
- package/dist/cjs/Sprinkle/prompts.js +12 -7
- package/dist/cjs/Sprinkle/prompts.js.map +1 -1
- package/dist/cjs/Sprinkle/schemas.js +17 -1
- package/dist/cjs/Sprinkle/schemas.js.map +1 -1
- package/dist/cjs/Sprinkle/type-guards.js +7 -1
- package/dist/cjs/Sprinkle/type-guards.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/action-integration.test.js +588 -0
- package/dist/esm/Sprinkle/__tests__/action-integration.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/action-registry.test.js +192 -0
- package/dist/esm/Sprinkle/__tests__/action-registry.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/action-runner.test.js +302 -0
- package/dist/esm/Sprinkle/__tests__/action-runner.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/builtin-actions.test.js +1107 -0
- package/dist/esm/Sprinkle/__tests__/builtin-actions.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/cli-adapter.test.js +742 -0
- package/dist/esm/Sprinkle/__tests__/cli-adapter.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js +15 -1
- package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/mcp-adapter.test.js +710 -0
- package/dist/esm/Sprinkle/__tests__/mcp-adapter.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/native-script.test.js +388 -0
- package/dist/esm/Sprinkle/__tests__/native-script.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/tui-helpers.test.js +332 -0
- package/dist/esm/Sprinkle/__tests__/tui-helpers.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/utility-actions.test.js +365 -0
- package/dist/esm/Sprinkle/__tests__/utility-actions.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/wallet-transaction-actions.test.js +747 -0
- package/dist/esm/Sprinkle/__tests__/wallet-transaction-actions.test.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/addressbook-actions.js +159 -0
- package/dist/esm/Sprinkle/actions/builtin/addressbook-actions.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/blaze-helper.js +55 -0
- package/dist/esm/Sprinkle/actions/builtin/blaze-helper.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/index.js +37 -0
- package/dist/esm/Sprinkle/actions/builtin/index.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/native-script.js +133 -0
- package/dist/esm/Sprinkle/actions/builtin/native-script.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/profile-actions.js +197 -0
- package/dist/esm/Sprinkle/actions/builtin/profile-actions.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/settings-actions.js +81 -0
- package/dist/esm/Sprinkle/actions/builtin/settings-actions.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/transaction-actions.js +340 -0
- package/dist/esm/Sprinkle/actions/builtin/transaction-actions.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/utility-actions.js +213 -0
- package/dist/esm/Sprinkle/actions/builtin/utility-actions.js.map +1 -0
- package/dist/esm/Sprinkle/actions/builtin/wallet-actions.js +207 -0
- package/dist/esm/Sprinkle/actions/builtin/wallet-actions.js.map +1 -0
- package/dist/esm/Sprinkle/actions/cli-adapter.js +379 -0
- package/dist/esm/Sprinkle/actions/cli-adapter.js.map +1 -0
- package/dist/esm/Sprinkle/actions/index.js +12 -0
- package/dist/esm/Sprinkle/actions/index.js.map +1 -0
- package/dist/esm/Sprinkle/actions/mcp-adapter.js +547 -0
- package/dist/esm/Sprinkle/actions/mcp-adapter.js.map +1 -0
- package/dist/esm/Sprinkle/actions/registry.js +85 -0
- package/dist/esm/Sprinkle/actions/registry.js.map +1 -0
- package/dist/esm/Sprinkle/actions/runner.js +182 -0
- package/dist/esm/Sprinkle/actions/runner.js.map +1 -0
- package/dist/esm/Sprinkle/actions/tui-helpers.js +91 -0
- package/dist/esm/Sprinkle/actions/tui-helpers.js.map +1 -0
- package/dist/esm/Sprinkle/actions/types.js +61 -0
- package/dist/esm/Sprinkle/actions/types.js.map +1 -0
- package/dist/esm/Sprinkle/index.js +517 -7
- package/dist/esm/Sprinkle/index.js.map +1 -1
- package/dist/esm/Sprinkle/prompts.js +12 -7
- package/dist/esm/Sprinkle/prompts.js.map +1 -1
- package/dist/esm/Sprinkle/schemas.js +16 -0
- package/dist/esm/Sprinkle/schemas.js.map +1 -1
- package/dist/esm/Sprinkle/type-guards.js +3 -0
- package/dist/esm/Sprinkle/type-guards.js.map +1 -1
- package/dist/types/Sprinkle/actions/builtin/addressbook-actions.d.ts +50 -0
- package/dist/types/Sprinkle/actions/builtin/addressbook-actions.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/builtin/blaze-helper.d.ts +39 -0
- package/dist/types/Sprinkle/actions/builtin/blaze-helper.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/builtin/index.d.ts +30 -0
- package/dist/types/Sprinkle/actions/builtin/index.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/builtin/native-script.d.ts +27 -0
- package/dist/types/Sprinkle/actions/builtin/native-script.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/builtin/profile-actions.d.ts +55 -0
- package/dist/types/Sprinkle/actions/builtin/profile-actions.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/builtin/settings-actions.d.ts +32 -0
- package/dist/types/Sprinkle/actions/builtin/settings-actions.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/builtin/transaction-actions.d.ts +70 -0
- package/dist/types/Sprinkle/actions/builtin/transaction-actions.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/builtin/utility-actions.d.ts +48 -0
- package/dist/types/Sprinkle/actions/builtin/utility-actions.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/builtin/wallet-actions.d.ts +50 -0
- package/dist/types/Sprinkle/actions/builtin/wallet-actions.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/cli-adapter.d.ts +104 -0
- package/dist/types/Sprinkle/actions/cli-adapter.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/index.d.ts +13 -0
- package/dist/types/Sprinkle/actions/index.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/mcp-adapter.d.ts +116 -0
- package/dist/types/Sprinkle/actions/mcp-adapter.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/registry.d.ts +42 -0
- package/dist/types/Sprinkle/actions/registry.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/runner.d.ts +45 -0
- package/dist/types/Sprinkle/actions/runner.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/tui-helpers.d.ts +53 -0
- package/dist/types/Sprinkle/actions/tui-helpers.d.ts.map +1 -0
- package/dist/types/Sprinkle/actions/types.d.ts +76 -0
- package/dist/types/Sprinkle/actions/types.d.ts.map +1 -0
- package/dist/types/Sprinkle/index.d.ts +84 -2
- package/dist/types/Sprinkle/index.d.ts.map +1 -1
- package/dist/types/Sprinkle/prompts.d.ts.map +1 -1
- package/dist/types/Sprinkle/schemas.d.ts +72 -0
- package/dist/types/Sprinkle/schemas.d.ts.map +1 -1
- package/dist/types/Sprinkle/type-guards.d.ts +4 -1
- package/dist/types/Sprinkle/type-guards.d.ts.map +1 -1
- package/dist/types/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +9 -2
- package/src/Sprinkle/__tests__/action-integration.test.ts +558 -0
- package/src/Sprinkle/__tests__/action-registry.test.ts +187 -0
- package/src/Sprinkle/__tests__/action-runner.test.ts +324 -0
- package/src/Sprinkle/__tests__/builtin-actions.test.ts +1022 -0
- package/src/Sprinkle/__tests__/cli-adapter.test.ts +736 -0
- package/src/Sprinkle/__tests__/fill-in-struct.test.ts +23 -1
- package/src/Sprinkle/__tests__/mcp-adapter.test.ts +720 -0
- package/src/Sprinkle/__tests__/native-script.test.ts +341 -0
- package/src/Sprinkle/__tests__/tui-helpers.test.ts +325 -0
- package/src/Sprinkle/__tests__/utility-actions.test.ts +348 -0
- package/src/Sprinkle/__tests__/wallet-transaction-actions.test.ts +695 -0
- package/src/Sprinkle/actions/builtin/addressbook-actions.ts +168 -0
- package/src/Sprinkle/actions/builtin/blaze-helper.ts +89 -0
- package/src/Sprinkle/actions/builtin/index.ts +125 -0
- package/src/Sprinkle/actions/builtin/native-script.ts +165 -0
- package/src/Sprinkle/actions/builtin/profile-actions.ts +229 -0
- package/src/Sprinkle/actions/builtin/settings-actions.ts +99 -0
- package/src/Sprinkle/actions/builtin/transaction-actions.ts +381 -0
- package/src/Sprinkle/actions/builtin/utility-actions.ts +285 -0
- package/src/Sprinkle/actions/builtin/wallet-actions.ts +233 -0
- package/src/Sprinkle/actions/cli-adapter.ts +446 -0
- package/src/Sprinkle/actions/index.ts +33 -0
- package/src/Sprinkle/actions/mcp-adapter.ts +638 -0
- package/src/Sprinkle/actions/registry.ts +97 -0
- package/src/Sprinkle/actions/runner.ts +200 -0
- package/src/Sprinkle/actions/tui-helpers.ts +114 -0
- package/src/Sprinkle/actions/types.ts +91 -0
- package/src/Sprinkle/index.ts +612 -3
- package/src/Sprinkle/prompts.ts +118 -72
- package/src/Sprinkle/schemas.ts +20 -0
- package/src/Sprinkle/type-guards.ts +9 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getWalletUtxos = exports.getWalletBalance = exports.getWalletAddress = void 0;
|
|
7
|
+
var _typebox = require("@sinclair/typebox");
|
|
8
|
+
var _sdk = require("@blaze-cardano/sdk");
|
|
9
|
+
var _types = require("../types.js");
|
|
10
|
+
var _blazeHelper = require("./blaze-helper.js");
|
|
11
|
+
/**
|
|
12
|
+
* Built-in wallet query actions for the Sprinkle action system.
|
|
13
|
+
* These actions expose wallet address, balance, and UTxO queries as
|
|
14
|
+
* non-interactive actions available in CLI and MCP modes.
|
|
15
|
+
*
|
|
16
|
+
* All actions use category "wallet".
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** Shared token entry shape for balance and UTxO output */
|
|
20
|
+
const TokenEntrySchema = _typebox.Type.Object({
|
|
21
|
+
policyId: _typebox.Type.String({
|
|
22
|
+
description: "Policy ID of the token"
|
|
23
|
+
}),
|
|
24
|
+
assetName: _typebox.Type.String({
|
|
25
|
+
description: "Asset name of the token (hex)"
|
|
26
|
+
}),
|
|
27
|
+
quantity: _typebox.Type.String({
|
|
28
|
+
description: "Token quantity as string (BigInt-safe)"
|
|
29
|
+
})
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* `get-wallet-address` -- Returns the primary change address of the configured wallet.
|
|
34
|
+
*/
|
|
35
|
+
const getWalletAddress = exports.getWalletAddress = {
|
|
36
|
+
name: "get-wallet-address",
|
|
37
|
+
description: "Get the primary address of the configured wallet.",
|
|
38
|
+
category: "wallet",
|
|
39
|
+
inputSchema: _typebox.Type.Object({}),
|
|
40
|
+
outputSchema: _typebox.Type.Object({
|
|
41
|
+
address: _typebox.Type.String({
|
|
42
|
+
description: "Bech32-encoded payment/change address"
|
|
43
|
+
}),
|
|
44
|
+
network: _typebox.Type.String({
|
|
45
|
+
description: "Network name (mainnet, preview, preprod)"
|
|
46
|
+
})
|
|
47
|
+
}),
|
|
48
|
+
execute: async (_input, context) => {
|
|
49
|
+
const blaze = await (0, _blazeHelper.getBlazeFromContext)(context);
|
|
50
|
+
let address;
|
|
51
|
+
try {
|
|
52
|
+
address = await blaze.wallet.getChangeAddress();
|
|
53
|
+
} catch (err) {
|
|
54
|
+
throw new _types.ActionError(`Failed to get wallet address: ${err instanceof Error ? err.message : String(err)}`, "NO_ADDRESS", {
|
|
55
|
+
error: err instanceof Error ? err.message : String(err)
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (!address) {
|
|
59
|
+
throw new _types.ActionError("The wallet returned no address. Ensure the wallet is properly configured.", "NO_ADDRESS");
|
|
60
|
+
}
|
|
61
|
+
const settings = context.settings;
|
|
62
|
+
const network = settings.network ?? "unknown";
|
|
63
|
+
return {
|
|
64
|
+
address: address.toBech32(),
|
|
65
|
+
network
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* `get-wallet-balance` -- Returns the ADA and token balance of the configured wallet.
|
|
72
|
+
* Aggregates lovelace and multi-asset amounts from all UTxOs.
|
|
73
|
+
* All quantities are returned as strings for BigInt-safe JSON serialization.
|
|
74
|
+
*/
|
|
75
|
+
const getWalletBalance = exports.getWalletBalance = {
|
|
76
|
+
name: "get-wallet-balance",
|
|
77
|
+
description: "Get the ADA and token balance of the configured wallet. Quantities returned as strings.",
|
|
78
|
+
category: "wallet",
|
|
79
|
+
inputSchema: _typebox.Type.Object({}),
|
|
80
|
+
outputSchema: _typebox.Type.Object({
|
|
81
|
+
lovelace: _typebox.Type.String({
|
|
82
|
+
description: "Total ADA balance in lovelace (as string for BigInt safety)"
|
|
83
|
+
}),
|
|
84
|
+
ada: _typebox.Type.String({
|
|
85
|
+
description: "Total ADA balance as decimal string"
|
|
86
|
+
}),
|
|
87
|
+
tokens: _typebox.Type.Array(TokenEntrySchema)
|
|
88
|
+
}),
|
|
89
|
+
execute: async (_input, context) => {
|
|
90
|
+
const blaze = await (0, _blazeHelper.getBlazeFromContext)(context);
|
|
91
|
+
let utxos;
|
|
92
|
+
try {
|
|
93
|
+
utxos = await blaze.wallet.getUnspentOutputs();
|
|
94
|
+
} catch (err) {
|
|
95
|
+
throw new _types.ActionError(`Provider error while fetching UTxOs: ${err instanceof Error ? err.message : String(err)}`, "PROVIDER_ERROR", {
|
|
96
|
+
error: err instanceof Error ? err.message : String(err)
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Aggregate lovelace and token amounts
|
|
101
|
+
let totalLovelace = 0n;
|
|
102
|
+
const tokenMap = new Map(); // key: `${policyId}.${assetName}`
|
|
103
|
+
|
|
104
|
+
for (const utxo of utxos) {
|
|
105
|
+
const value = utxo.output().amount();
|
|
106
|
+
totalLovelace += value.coin();
|
|
107
|
+
const multiasset = value.multiasset();
|
|
108
|
+
if (multiasset) {
|
|
109
|
+
for (const [assetId, quantity] of multiasset.entries()) {
|
|
110
|
+
const policyId = _sdk.Core.AssetId.getPolicyId(assetId);
|
|
111
|
+
const assetName = _sdk.Core.AssetId.getAssetName(assetId);
|
|
112
|
+
const key = `${policyId}.${assetName}`;
|
|
113
|
+
tokenMap.set(key, (tokenMap.get(key) ?? 0n) + quantity);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Convert tokens map to array, serializing BigInt quantities as strings
|
|
119
|
+
const tokens = Array.from(tokenMap.entries()).map(([key, quantity]) => {
|
|
120
|
+
const [policyId, assetName] = key.split(".");
|
|
121
|
+
return {
|
|
122
|
+
policyId: policyId ?? "",
|
|
123
|
+
assetName: assetName ?? "",
|
|
124
|
+
quantity: quantity.toString()
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// ADA = lovelace / 1_000_000, with 6 decimal places
|
|
129
|
+
const adaWhole = totalLovelace / 1_000_000n;
|
|
130
|
+
const adaFraction = totalLovelace % 1_000_000n;
|
|
131
|
+
const ada = `${adaWhole}.${adaFraction.toString().padStart(6, "0")}`;
|
|
132
|
+
return {
|
|
133
|
+
lovelace: totalLovelace.toString(),
|
|
134
|
+
ada,
|
|
135
|
+
tokens
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* `get-wallet-utxos` -- Returns raw UTxO set for the configured wallet.
|
|
142
|
+
* Accepts an optional limit (default 100). Returns UTxOs and the total count.
|
|
143
|
+
*/
|
|
144
|
+
const getWalletUtxos = exports.getWalletUtxos = {
|
|
145
|
+
name: "get-wallet-utxos",
|
|
146
|
+
description: "Get the UTxO set for the configured wallet.",
|
|
147
|
+
category: "wallet",
|
|
148
|
+
inputSchema: _typebox.Type.Object({
|
|
149
|
+
limit: _typebox.Type.Optional(_typebox.Type.Number({
|
|
150
|
+
default: 100,
|
|
151
|
+
description: "Maximum number of UTxOs to return"
|
|
152
|
+
}))
|
|
153
|
+
}),
|
|
154
|
+
outputSchema: _typebox.Type.Object({
|
|
155
|
+
utxos: _typebox.Type.Array(_typebox.Type.Object({
|
|
156
|
+
txHash: _typebox.Type.String({
|
|
157
|
+
description: "Transaction hash of the UTxO"
|
|
158
|
+
}),
|
|
159
|
+
outputIndex: _typebox.Type.Number({
|
|
160
|
+
description: "Output index within the transaction"
|
|
161
|
+
}),
|
|
162
|
+
lovelace: _typebox.Type.String({
|
|
163
|
+
description: "Lovelace amount as string (BigInt-safe)"
|
|
164
|
+
}),
|
|
165
|
+
tokens: _typebox.Type.Array(TokenEntrySchema)
|
|
166
|
+
})),
|
|
167
|
+
total: _typebox.Type.Number({
|
|
168
|
+
description: "Total number of UTxOs (before limit)"
|
|
169
|
+
})
|
|
170
|
+
}),
|
|
171
|
+
execute: async (input, context) => {
|
|
172
|
+
const blaze = await (0, _blazeHelper.getBlazeFromContext)(context);
|
|
173
|
+
const limit = input.limit ?? 100;
|
|
174
|
+
let allUtxos;
|
|
175
|
+
try {
|
|
176
|
+
allUtxos = await blaze.wallet.getUnspentOutputs();
|
|
177
|
+
} catch (err) {
|
|
178
|
+
throw new _types.ActionError(`Provider error while fetching UTxOs: ${err instanceof Error ? err.message : String(err)}`, "PROVIDER_ERROR", {
|
|
179
|
+
error: err instanceof Error ? err.message : String(err)
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
const total = allUtxos.length;
|
|
183
|
+
const limited = allUtxos.slice(0, limit);
|
|
184
|
+
const utxos = limited.map(utxo => {
|
|
185
|
+
const input = utxo.input();
|
|
186
|
+
const output = utxo.output();
|
|
187
|
+
const value = output.amount();
|
|
188
|
+
const tokens = [];
|
|
189
|
+
const multiasset = value.multiasset();
|
|
190
|
+
if (multiasset) {
|
|
191
|
+
for (const [assetId, quantity] of multiasset.entries()) {
|
|
192
|
+
tokens.push({
|
|
193
|
+
policyId: _sdk.Core.AssetId.getPolicyId(assetId),
|
|
194
|
+
assetName: _sdk.Core.AssetId.getAssetName(assetId),
|
|
195
|
+
quantity: quantity.toString()
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
txHash: input.transactionId().toString(),
|
|
201
|
+
outputIndex: Number(input.index()),
|
|
202
|
+
lovelace: value.coin().toString(),
|
|
203
|
+
tokens
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
return {
|
|
207
|
+
utxos,
|
|
208
|
+
total
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
//# sourceMappingURL=wallet-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet-actions.js","names":["_typebox","require","_sdk","_types","_blazeHelper","TokenEntrySchema","Type","Object","policyId","String","description","assetName","quantity","getWalletAddress","exports","name","category","inputSchema","outputSchema","address","network","execute","_input","context","blaze","getBlazeFromContext","wallet","getChangeAddress","err","ActionError","Error","message","error","settings","toBech32","getWalletBalance","lovelace","ada","tokens","Array","utxos","getUnspentOutputs","totalLovelace","tokenMap","Map","utxo","value","output","amount","coin","multiasset","assetId","entries","Core","AssetId","getPolicyId","getAssetName","key","set","get","from","map","split","toString","adaWhole","adaFraction","padStart","getWalletUtxos","limit","Optional","Number","default","txHash","outputIndex","total","input","allUtxos","length","limited","slice","push","transactionId","index"],"sources":["../../../../../src/Sprinkle/actions/builtin/wallet-actions.ts"],"sourcesContent":["/**\n * Built-in wallet query actions for the Sprinkle action system.\n * These actions expose wallet address, balance, and UTxO queries as\n * non-interactive actions available in CLI and MCP modes.\n *\n * All actions use category \"wallet\".\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport type { TSchema } from \"@sinclair/typebox\";\nimport { Core } from \"@blaze-cardano/sdk\";\nimport { ActionError } from \"../types.js\";\nimport type { IAction } from \"../types.js\";\nimport { getBlazeFromContext } from \"./blaze-helper.js\";\n\n/** Shared token entry shape for balance and UTxO output */\nconst TokenEntrySchema = Type.Object({\n policyId: Type.String({ description: \"Policy ID of the token\" }),\n assetName: Type.String({ description: \"Asset name of the token (hex)\" }),\n quantity: Type.String({ description: \"Token quantity as string (BigInt-safe)\" }),\n});\n\n/**\n * `get-wallet-address` -- Returns the primary change address of the configured wallet.\n */\nexport const getWalletAddress: IAction<\n Record<string, never>,\n { address: string; network: string },\n TSchema\n> = {\n name: \"get-wallet-address\",\n description: \"Get the primary address of the configured wallet.\",\n category: \"wallet\",\n inputSchema: Type.Object({}),\n outputSchema: Type.Object({\n address: Type.String({ description: \"Bech32-encoded payment/change address\" }),\n network: Type.String({ description: \"Network name (mainnet, preview, preprod)\" }),\n }),\n execute: async (_input, context) => {\n const blaze = await getBlazeFromContext(context);\n\n let address: Core.Address;\n try {\n address = await blaze.wallet.getChangeAddress();\n } catch (err) {\n throw new ActionError(\n `Failed to get wallet address: ${err instanceof Error ? err.message : String(err)}`,\n \"NO_ADDRESS\",\n { error: err instanceof Error ? err.message : String(err) },\n );\n }\n\n if (!address) {\n throw new ActionError(\n \"The wallet returned no address. Ensure the wallet is properly configured.\",\n \"NO_ADDRESS\",\n );\n }\n\n const settings = context.settings as unknown as { network?: string };\n const network = settings.network ?? \"unknown\";\n\n return {\n address: address.toBech32(),\n network,\n };\n },\n};\n\n/**\n * `get-wallet-balance` -- Returns the ADA and token balance of the configured wallet.\n * Aggregates lovelace and multi-asset amounts from all UTxOs.\n * All quantities are returned as strings for BigInt-safe JSON serialization.\n */\nexport const getWalletBalance: IAction<\n Record<string, never>,\n {\n lovelace: string;\n ada: string;\n tokens: Array<{ policyId: string; assetName: string; quantity: string }>;\n },\n TSchema\n> = {\n name: \"get-wallet-balance\",\n description:\n \"Get the ADA and token balance of the configured wallet. Quantities returned as strings.\",\n category: \"wallet\",\n inputSchema: Type.Object({}),\n outputSchema: Type.Object({\n lovelace: Type.String({\n description: \"Total ADA balance in lovelace (as string for BigInt safety)\",\n }),\n ada: Type.String({ description: \"Total ADA balance as decimal string\" }),\n tokens: Type.Array(TokenEntrySchema),\n }),\n execute: async (_input, context) => {\n const blaze = await getBlazeFromContext(context);\n\n let utxos: Awaited<ReturnType<typeof blaze.wallet.getUnspentOutputs>>;\n try {\n utxos = await blaze.wallet.getUnspentOutputs();\n } catch (err) {\n throw new ActionError(\n `Provider error while fetching UTxOs: ${err instanceof Error ? err.message : String(err)}`,\n \"PROVIDER_ERROR\",\n { error: err instanceof Error ? err.message : String(err) },\n );\n }\n\n // Aggregate lovelace and token amounts\n let totalLovelace = 0n;\n const tokenMap = new Map<string, bigint>(); // key: `${policyId}.${assetName}`\n\n for (const utxo of utxos) {\n const value = utxo.output().amount();\n totalLovelace += value.coin();\n\n const multiasset = value.multiasset();\n if (multiasset) {\n for (const [assetId, quantity] of multiasset.entries()) {\n const policyId = Core.AssetId.getPolicyId(assetId);\n const assetName = Core.AssetId.getAssetName(assetId);\n const key = `${policyId}.${assetName}`;\n tokenMap.set(key, (tokenMap.get(key) ?? 0n) + quantity);\n }\n }\n }\n\n // Convert tokens map to array, serializing BigInt quantities as strings\n const tokens = Array.from(tokenMap.entries()).map(([key, quantity]) => {\n const [policyId, assetName] = key.split(\".\");\n return {\n policyId: policyId ?? \"\",\n assetName: assetName ?? \"\",\n quantity: quantity.toString(),\n };\n });\n\n // ADA = lovelace / 1_000_000, with 6 decimal places\n const adaWhole = totalLovelace / 1_000_000n;\n const adaFraction = totalLovelace % 1_000_000n;\n const ada = `${adaWhole}.${adaFraction.toString().padStart(6, \"0\")}`;\n\n return {\n lovelace: totalLovelace.toString(),\n ada,\n tokens,\n };\n },\n};\n\n/**\n * `get-wallet-utxos` -- Returns raw UTxO set for the configured wallet.\n * Accepts an optional limit (default 100). Returns UTxOs and the total count.\n */\nexport const getWalletUtxos: IAction<\n { limit?: number },\n {\n utxos: Array<{\n txHash: string;\n outputIndex: number;\n lovelace: string;\n tokens: Array<{ policyId: string; assetName: string; quantity: string }>;\n }>;\n total: number;\n },\n TSchema\n> = {\n name: \"get-wallet-utxos\",\n description: \"Get the UTxO set for the configured wallet.\",\n category: \"wallet\",\n inputSchema: Type.Object({\n limit: Type.Optional(\n Type.Number({ default: 100, description: \"Maximum number of UTxOs to return\" }),\n ),\n }),\n outputSchema: Type.Object({\n utxos: Type.Array(\n Type.Object({\n txHash: Type.String({ description: \"Transaction hash of the UTxO\" }),\n outputIndex: Type.Number({ description: \"Output index within the transaction\" }),\n lovelace: Type.String({ description: \"Lovelace amount as string (BigInt-safe)\" }),\n tokens: Type.Array(TokenEntrySchema),\n }),\n ),\n total: Type.Number({ description: \"Total number of UTxOs (before limit)\" }),\n }),\n execute: async (input, context) => {\n const blaze = await getBlazeFromContext(context);\n const limit = input.limit ?? 100;\n\n let allUtxos: Awaited<ReturnType<typeof blaze.wallet.getUnspentOutputs>>;\n try {\n allUtxos = await blaze.wallet.getUnspentOutputs();\n } catch (err) {\n throw new ActionError(\n `Provider error while fetching UTxOs: ${err instanceof Error ? err.message : String(err)}`,\n \"PROVIDER_ERROR\",\n { error: err instanceof Error ? err.message : String(err) },\n );\n }\n\n const total = allUtxos.length;\n const limited = allUtxos.slice(0, limit);\n\n const utxos = limited.map((utxo) => {\n const input = utxo.input();\n const output = utxo.output();\n const value = output.amount();\n\n const tokens: Array<{ policyId: string; assetName: string; quantity: string }> = [];\n const multiasset = value.multiasset();\n if (multiasset) {\n for (const [assetId, quantity] of multiasset.entries()) {\n tokens.push({\n policyId: Core.AssetId.getPolicyId(assetId),\n assetName: Core.AssetId.getAssetName(assetId),\n quantity: quantity.toString(),\n });\n }\n }\n\n return {\n txHash: input.transactionId().toString(),\n outputIndex: Number(input.index()),\n lovelace: value.coin().toString(),\n tokens,\n };\n });\n\n return { utxos, total };\n },\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.camelToKebab = camelToKebab;
|
|
7
|
+
exports.coerceValue = coerceValue;
|
|
8
|
+
exports.generateActionHelp = generateActionHelp;
|
|
9
|
+
exports.generateAppHelp = generateAppHelp;
|
|
10
|
+
exports.kebabToCamel = kebabToCamel;
|
|
11
|
+
exports.parseArgvWithSchema = parseArgvWithSchema;
|
|
12
|
+
exports.runCli = runCli;
|
|
13
|
+
var _encryption = require("../encryption.js");
|
|
14
|
+
var _typeGuards = require("../type-guards.js");
|
|
15
|
+
var _runner = require("./runner.js");
|
|
16
|
+
/**
|
|
17
|
+
* CLI adapter for Sprinkles actions.
|
|
18
|
+
*
|
|
19
|
+
* Provides:
|
|
20
|
+
* - Case-conversion helpers (camelToKebab / kebabToCamel)
|
|
21
|
+
* - Schema-driven type coercion (coerceValue / parseArgvWithSchema)
|
|
22
|
+
* - Help text generation (generateActionHelp / generateAppHelp)
|
|
23
|
+
* - CLI orchestrator (runCli)
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// Re-import Sprinkle as a type only to avoid circular deps
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Case conversion helpers
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Convert a camelCase string to kebab-case.
|
|
34
|
+
* Examples:
|
|
35
|
+
* "myFlagName" -> "my-flag-name"
|
|
36
|
+
* "getBalance" -> "get-balance"
|
|
37
|
+
* "URL" -> "u-r-l" (each uppercase letter gets a dash)
|
|
38
|
+
*/
|
|
39
|
+
function camelToKebab(str) {
|
|
40
|
+
if (!str) return str;
|
|
41
|
+
return str.replace(/([A-Z])/g, match => `-${match.toLowerCase()}`).replace(/^-/, "");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Convert a kebab-case string to camelCase.
|
|
46
|
+
* Examples:
|
|
47
|
+
* "my-flag-name" -> "myFlagName"
|
|
48
|
+
* "get-balance" -> "getBalance"
|
|
49
|
+
*/
|
|
50
|
+
function kebabToCamel(str) {
|
|
51
|
+
if (!str) return str;
|
|
52
|
+
return str.replace(/-([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Schema-driven type coercion
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Coerce a raw CLI string value to the type expected by a TypeBox schema.
|
|
61
|
+
*
|
|
62
|
+
* Handles:
|
|
63
|
+
* - Number / Integer: parseFloat / parseInt
|
|
64
|
+
* - Boolean: "true"/"false" strings, or passthrough if already boolean
|
|
65
|
+
* - BigInt: BigInt() constructor
|
|
66
|
+
* - Array: already-array passthrough; single value wrapped in array
|
|
67
|
+
* - Object: JSON string parse
|
|
68
|
+
* - String: passthrough
|
|
69
|
+
* - Optional: unwrap and recurse on inner schema
|
|
70
|
+
* - Union: passthrough (caller should supply JSON; no schema-level heuristics)
|
|
71
|
+
*/
|
|
72
|
+
function coerceValue(raw, schema) {
|
|
73
|
+
// Note: TypeBox Optional<T> adds an [OptionalKind] marker but does not
|
|
74
|
+
// change the schema Kind. The guards below work correctly on Optional types.
|
|
75
|
+
|
|
76
|
+
// If the raw value is null or undefined, return as-is
|
|
77
|
+
if (raw === null || raw === undefined) return raw;
|
|
78
|
+
if ((0, _typeGuards.isNumber)(schema)) {
|
|
79
|
+
if (typeof raw === "number") return raw;
|
|
80
|
+
if (typeof raw === "string") {
|
|
81
|
+
const n = parseFloat(raw);
|
|
82
|
+
return isNaN(n) ? raw : n;
|
|
83
|
+
}
|
|
84
|
+
return raw;
|
|
85
|
+
}
|
|
86
|
+
if ((0, _typeGuards.isInteger)(schema)) {
|
|
87
|
+
if (typeof raw === "number") return Math.trunc(raw);
|
|
88
|
+
if (typeof raw === "string") {
|
|
89
|
+
const n = parseInt(raw, 10);
|
|
90
|
+
return isNaN(n) ? raw : n;
|
|
91
|
+
}
|
|
92
|
+
return raw;
|
|
93
|
+
}
|
|
94
|
+
if ((0, _typeGuards.isBoolean)(schema)) {
|
|
95
|
+
if (typeof raw === "boolean") return raw;
|
|
96
|
+
if (raw === "true") return true;
|
|
97
|
+
if (raw === "false") return false;
|
|
98
|
+
return raw;
|
|
99
|
+
}
|
|
100
|
+
if ((0, _typeGuards.isBigInt)(schema)) {
|
|
101
|
+
if (typeof raw === "bigint") return raw;
|
|
102
|
+
if (typeof raw === "string" || typeof raw === "number") {
|
|
103
|
+
try {
|
|
104
|
+
return BigInt(raw);
|
|
105
|
+
} catch {
|
|
106
|
+
return raw;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return raw;
|
|
110
|
+
}
|
|
111
|
+
if ((0, _typeGuards.isArray)(schema)) {
|
|
112
|
+
const itemSchema = schema.items;
|
|
113
|
+
if (Array.isArray(raw)) {
|
|
114
|
+
if (itemSchema) {
|
|
115
|
+
return raw.map(item => coerceValue(item, itemSchema));
|
|
116
|
+
}
|
|
117
|
+
return raw;
|
|
118
|
+
}
|
|
119
|
+
// Single value: wrap in array
|
|
120
|
+
const singleValue = itemSchema ? coerceValue(raw, itemSchema) : raw;
|
|
121
|
+
return [singleValue];
|
|
122
|
+
}
|
|
123
|
+
if ((0, _typeGuards.isObject)(schema)) {
|
|
124
|
+
let obj = raw;
|
|
125
|
+
// If it's a JSON string, parse it
|
|
126
|
+
if (typeof raw === "string") {
|
|
127
|
+
const trimmed = raw.trim();
|
|
128
|
+
if (trimmed.startsWith("{")) {
|
|
129
|
+
try {
|
|
130
|
+
obj = JSON.parse(trimmed);
|
|
131
|
+
} catch {
|
|
132
|
+
return raw;
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
return raw;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Recurse into properties to coerce nested values
|
|
139
|
+
if (typeof obj === "object" && obj !== null && !Array.isArray(obj)) {
|
|
140
|
+
const props = schema.properties;
|
|
141
|
+
if (props) {
|
|
142
|
+
const result = {
|
|
143
|
+
...obj
|
|
144
|
+
};
|
|
145
|
+
for (const [key, propSchema] of Object.entries(props)) {
|
|
146
|
+
if (key in result) {
|
|
147
|
+
result[key] = coerceValue(result[key], propSchema);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return obj;
|
|
154
|
+
}
|
|
155
|
+
if ((0, _typeGuards.isString)(schema)) {
|
|
156
|
+
if (typeof raw === "string") return raw;
|
|
157
|
+
return String(raw);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Union / unknown / other: return as-is (caller provides JSON)
|
|
161
|
+
return raw;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Walk a TypeBox object schema and coerce each property value from raw CLI args.
|
|
166
|
+
*
|
|
167
|
+
* - Handles kebab-case -> camelCase property name mapping
|
|
168
|
+
* - Applies coerceValue for each property
|
|
169
|
+
* - Applies TypeBox defaults for omitted optional fields
|
|
170
|
+
*
|
|
171
|
+
* @param rawArgs - Key/value record from parseCliArgs (keys may be kebab-case)
|
|
172
|
+
* @param schema - A TypeBox TObject schema
|
|
173
|
+
* @returns A new record with coerced values
|
|
174
|
+
*/
|
|
175
|
+
function parseArgvWithSchema(rawArgs, schema) {
|
|
176
|
+
if (!(0, _typeGuards.isObject)(schema)) {
|
|
177
|
+
// Non-object schema: return args as-is (best-effort)
|
|
178
|
+
return rawArgs;
|
|
179
|
+
}
|
|
180
|
+
const result = {};
|
|
181
|
+
const properties = schema.properties;
|
|
182
|
+
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
183
|
+
// Look up both camelCase and kebab-case versions in rawArgs
|
|
184
|
+
const kebabName = camelToKebab(propName);
|
|
185
|
+
let rawValue = undefined;
|
|
186
|
+
if (propName in rawArgs) {
|
|
187
|
+
rawValue = rawArgs[propName];
|
|
188
|
+
} else if (kebabName !== propName && kebabName in rawArgs) {
|
|
189
|
+
rawValue = rawArgs[kebabName];
|
|
190
|
+
}
|
|
191
|
+
if (rawValue === undefined) {
|
|
192
|
+
// Apply default if defined on schema
|
|
193
|
+
if ((0, _typeGuards.hasDefault)(propSchema)) {
|
|
194
|
+
result[propName] = (0, _typeGuards.getDefault)(propSchema);
|
|
195
|
+
}
|
|
196
|
+
// Else omit: Value.Check will handle required/optional enforcement
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
result[propName] = coerceValue(rawValue, propSchema);
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
// Help text generation
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Describe a single TypeBox schema in a human-readable CLI type label.
|
|
210
|
+
*/
|
|
211
|
+
function describeType(schema) {
|
|
212
|
+
// Note: isOptional() only checks the OptionalKind marker; the other guards
|
|
213
|
+
// still work correctly on Optional-wrapped schemas.
|
|
214
|
+
if ((0, _typeGuards.isString)(schema)) return "<string>";
|
|
215
|
+
if ((0, _typeGuards.isNumber)(schema)) return "<number>";
|
|
216
|
+
if ((0, _typeGuards.isInteger)(schema)) return "<integer>";
|
|
217
|
+
if ((0, _typeGuards.isBoolean)(schema)) return "<boolean>";
|
|
218
|
+
if ((0, _typeGuards.isBigInt)(schema)) return "<bigint>";
|
|
219
|
+
if ((0, _typeGuards.isArray)(schema)) {
|
|
220
|
+
const itemSchema = schema.items;
|
|
221
|
+
const itemType = itemSchema ? describeType(itemSchema) : "<value>";
|
|
222
|
+
return `${itemType}... (repeatable)`;
|
|
223
|
+
}
|
|
224
|
+
if ((0, _typeGuards.isObject)(schema)) return "<json>";
|
|
225
|
+
if ((0, _typeGuards.isUnion)(schema)) return "<json>";
|
|
226
|
+
return "<value>";
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Generate action-specific help text.
|
|
231
|
+
*
|
|
232
|
+
* Format:
|
|
233
|
+
* ```
|
|
234
|
+
* Usage: <appName> <action-name> [options]
|
|
235
|
+
*
|
|
236
|
+
* Description
|
|
237
|
+
*
|
|
238
|
+
* Options:
|
|
239
|
+
* --flag-name <type> Description [default: x] (required/optional)
|
|
240
|
+
* ...
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
243
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
244
|
+
function generateActionHelp(action, appName) {
|
|
245
|
+
const app = appName ?? "app";
|
|
246
|
+
const lines = [`Usage: ${app} ${action.name} [options]`, "", action.description, "", "Options:"];
|
|
247
|
+
const schema = action.inputSchema;
|
|
248
|
+
if ((0, _typeGuards.isObject)(schema)) {
|
|
249
|
+
const properties = schema.properties;
|
|
250
|
+
const required = schema.required ?? [];
|
|
251
|
+
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
252
|
+
const flagName = camelToKebab(propName);
|
|
253
|
+
const typeLabel = describeType(propSchema);
|
|
254
|
+
const isReq = required.includes(propName);
|
|
255
|
+
const defaultVal = (0, _typeGuards.hasDefault)(propSchema) ? (0, _typeGuards.getDefault)(propSchema) : undefined;
|
|
256
|
+
const description = propSchema.description ?? "";
|
|
257
|
+
const requiredLabel = isReq ? "(required)" : "(optional)";
|
|
258
|
+
const defaultLabel = defaultVal !== undefined ? ` [default: ${String(defaultVal)}]` : "";
|
|
259
|
+
const descPart = description ? ` ${description}` : "";
|
|
260
|
+
lines.push(` --${flagName} ${typeLabel}${descPart}${defaultLabel} ${requiredLabel}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
lines.push("");
|
|
264
|
+
lines.push(" --help Show this help message");
|
|
265
|
+
return lines.join("\n");
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Generate application-level help listing all registered actions.
|
|
270
|
+
*
|
|
271
|
+
* Format:
|
|
272
|
+
* ```
|
|
273
|
+
* Usage: <appName> <action> [options]
|
|
274
|
+
*
|
|
275
|
+
* Available actions:
|
|
276
|
+
*
|
|
277
|
+
* category:
|
|
278
|
+
* action-name Description
|
|
279
|
+
*
|
|
280
|
+
* Global options:
|
|
281
|
+
* --help Show this help message
|
|
282
|
+
* --profile <n> Use profile by name
|
|
283
|
+
* ```
|
|
284
|
+
*/
|
|
285
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
286
|
+
function generateAppHelp(
|
|
287
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
288
|
+
actions, appName) {
|
|
289
|
+
const app = appName ?? "app";
|
|
290
|
+
const lines = [`Usage: ${app} <action> [options]`, ""];
|
|
291
|
+
if (actions.length === 0) {
|
|
292
|
+
lines.push("No actions registered.");
|
|
293
|
+
} else {
|
|
294
|
+
lines.push("Available actions:");
|
|
295
|
+
|
|
296
|
+
// Group by category
|
|
297
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
298
|
+
const byCategory = new Map();
|
|
299
|
+
for (const action of actions) {
|
|
300
|
+
const cat = action.category ?? "default";
|
|
301
|
+
const bucket = byCategory.get(cat);
|
|
302
|
+
if (bucket) {
|
|
303
|
+
bucket.push(action);
|
|
304
|
+
} else {
|
|
305
|
+
byCategory.set(cat, [action]);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
for (const [category, categoryActions] of byCategory) {
|
|
309
|
+
if (category !== "default") {
|
|
310
|
+
lines.push("");
|
|
311
|
+
lines.push(` ${category}:`);
|
|
312
|
+
}
|
|
313
|
+
for (const action of categoryActions) {
|
|
314
|
+
lines.push(` ${action.name.padEnd(30)} ${action.description}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
lines.push("");
|
|
319
|
+
lines.push("Global options:");
|
|
320
|
+
lines.push(" --help Show this help message");
|
|
321
|
+
lines.push(" --profile <n> Use profile by name");
|
|
322
|
+
return lines.join("\n");
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// ---------------------------------------------------------------------------
|
|
326
|
+
// CLI orchestrator
|
|
327
|
+
// ---------------------------------------------------------------------------
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Run an action from CLI arguments, writing JSON output to stdout/stderr.
|
|
331
|
+
*
|
|
332
|
+
* Handles:
|
|
333
|
+
* - Action not found: JSON error to stderr, process.exit(1)
|
|
334
|
+
* - Action help (`--help` in rawArgs): prints action help to stdout
|
|
335
|
+
* - Schema-driven argument coercion via parseArgvWithSchema
|
|
336
|
+
* - Success: `{"success":true,"data":...}` JSON to stdout
|
|
337
|
+
* - Failure: `{"success":false,"error":...}` JSON to stderr, process.exit(1)
|
|
338
|
+
*
|
|
339
|
+
* @param sprinkle - Fully-initialized Sprinkle instance
|
|
340
|
+
* @param actionName - The action to invoke
|
|
341
|
+
* @param rawArgs - Pre-parsed key/value args from parseCliArgs (profile already removed)
|
|
342
|
+
* @param context - The action execution context
|
|
343
|
+
* @param appName - Optional app name for help text
|
|
344
|
+
*/
|
|
345
|
+
async function runCli(sprinkle, actionName, rawArgs, context, appName) {
|
|
346
|
+
const action = sprinkle.getAction(actionName);
|
|
347
|
+
if (!action) {
|
|
348
|
+
const available = sprinkle.listActions().map(a => a.name).join(", ");
|
|
349
|
+
const errorOutput = JSON.stringify({
|
|
350
|
+
success: false,
|
|
351
|
+
error: {
|
|
352
|
+
code: "ACTION_NOT_FOUND",
|
|
353
|
+
message: `Action "${actionName}" not found. Available actions: ${available || "(none)"}`
|
|
354
|
+
}
|
|
355
|
+
}, _encryption.bigIntReplacer);
|
|
356
|
+
console.error(errorOutput);
|
|
357
|
+
process.exit(1);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Handle --help flag for action-specific help
|
|
361
|
+
if (rawArgs["help"] === true) {
|
|
362
|
+
console.log(generateActionHelp(action, appName));
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Coerce raw string args using the action's input schema
|
|
367
|
+
const coercedInput = parseArgvWithSchema(rawArgs, action.inputSchema);
|
|
368
|
+
|
|
369
|
+
// Execute and output result
|
|
370
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
371
|
+
const result = await (0, _runner.executeAction)(action, coercedInput, context);
|
|
372
|
+
if (result.success) {
|
|
373
|
+
console.log(JSON.stringify({
|
|
374
|
+
success: true,
|
|
375
|
+
data: result.data
|
|
376
|
+
}, _encryption.bigIntReplacer));
|
|
377
|
+
} else {
|
|
378
|
+
const errorOutput = JSON.stringify({
|
|
379
|
+
success: false,
|
|
380
|
+
error: {
|
|
381
|
+
code: result.error.code,
|
|
382
|
+
message: result.error.message,
|
|
383
|
+
details: result.error.details
|
|
384
|
+
}
|
|
385
|
+
}, _encryption.bigIntReplacer);
|
|
386
|
+
console.error(errorOutput);
|
|
387
|
+
process.exit(1);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
//# sourceMappingURL=cli-adapter.js.map
|