@thirdfy/agent-cli 0.2.86 → 0.4.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/CHANGELOG.md +116 -0
- package/README.md +61 -25
- package/package.json +2 -2
- package/scripts/validate-cli-contract-schemas.mjs +5 -0
- package/src/cli/errors.mjs +58 -8
- package/src/cli/help.mjs +0 -3
- package/src/cli/manifest.mjs +54 -27
- package/src/cli/options/bootstrap.mjs +15 -3
- package/src/cli/options/chains.mjs +5 -0
- package/src/cli/options/credits.mjs +9 -0
- package/src/cli/options/data.mjs +13 -1
- package/src/cli/options/index.mjs +10 -4
- package/src/cli/options/walletControl.mjs +8 -0
- package/src/commands/bootstrap.mjs +44 -5
- package/src/commands/chat.mjs +3 -0
- package/src/commands/credits.mjs +39 -4
- package/src/commands/delegation.mjs +3 -1
- package/src/commands/discovery.mjs +156 -13
- package/src/commands/doctor.mjs +5 -2
- package/src/commands/execute.mjs +96 -3
- package/src/commands/prompt.mjs +5 -4
- package/src/commands/wallet.mjs +119 -3
- package/src/commands/walletControl.mjs +66 -0
- package/src/contracts/cli/schemas/actions.response.schema.json +45 -0
- package/src/contracts/cli/schemas/chains-non-evm.response.schema.json +76 -0
- package/src/contracts/cli/schemas/chains.response.schema.json +151 -0
- package/src/contracts/cli/schemas/error.response.schema.json +61 -0
- package/src/contracts/cli/schemas/preview.response.schema.json +179 -0
- package/src/contracts/cli/schemas/readiness.response.schema.json +94 -0
- package/src/core/args.mjs +10 -2
- package/src/core/chainRegistry.mjs +223 -1
- package/src/core/context.mjs +37 -14
- package/src/core/errorEnvelope.mjs +209 -0
- package/src/core/fundingTokenIn.mjs +24 -1
- package/src/core/http.mjs +6 -1
- package/src/core/readOnlyActions.mjs +10 -0
- package/src/core/walletExecuteChainId.mjs +25 -0
- package/src/lib/creditsUsdSummary.mjs +48 -4
- package/src/runtime/actions/actionList.mjs +87 -0
- package/src/runtime/actions/selection.mjs +17 -22
- package/src/runtime/execution/actionPreflight.mjs +50 -14
- package/src/runtime/execution/payloads.mjs +36 -28
- package/src/runtime/execution/runners.mjs +75 -21
- package/src/runtime/execution/svmLane.mjs +106 -0
- package/src/runtime/execution/walletControl.mjs +104 -0
- package/src/runtime/handlers.mjs +16 -2
- package/src/runtime/index.mjs +1 -1
- package/src/runtime/main.mjs +21 -5
- package/src/runtime/providerHints/apps.mjs +36 -0
- package/src/runtime/providerHints/catalogHint.mjs +55 -0
- package/src/runtime/providerHints/cex.mjs +130 -0
- package/src/runtime/providerHints/data.mjs +144 -0
- package/src/runtime/providerHints/dispatch.mjs +177 -0
- package/src/runtime/providerHints/dogeos.mjs +38 -0
- package/src/runtime/providerHints/earn.mjs +201 -0
- package/src/runtime/providerHints/perps.mjs +346 -0
- package/src/runtime/providerHints/prediction.mjs +128 -0
- package/src/runtime/providerHints/solana.mjs +85 -0
- package/src/runtime/providerHints/trading.mjs +78 -0
- package/src/runtime/providerHints/walletControl.mjs +39 -0
- package/src/runtime/risk/notional.mjs +59 -0
- package/src/runtime/risk/orderPreview.mjs +154 -0
- package/src/runtime/risk/riskRefusal.mjs +74 -0
- package/src/runtime/validation/actionParamsGate.mjs +2 -0
- package/src/runtime/providerHints.mjs +0 -1017
package/src/cli/manifest.mjs
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* @property {string} [description]
|
|
11
11
|
* @property {object} [args] - Commander arguments, e.g. { email: '<address>' }
|
|
12
12
|
* @property {string} [trackKind] - for commandTrackList: 'actions' | 'events'
|
|
13
|
-
* @property {boolean} [jeffAlias] - maps jeff * to root handlers
|
|
14
13
|
*/
|
|
15
14
|
|
|
16
15
|
/** @type {ManifestEntry[]} */
|
|
@@ -72,13 +71,13 @@ export const CLI_MANIFEST = [
|
|
|
72
71
|
{
|
|
73
72
|
path: ['help', 'onboarding'],
|
|
74
73
|
handler: 'commandHelpOnboarding',
|
|
75
|
-
options: ['chains'],
|
|
74
|
+
options: ['chains', 'onboardingHelp'],
|
|
76
75
|
description: 'Structured onboarding help (JSON envelope)',
|
|
77
76
|
},
|
|
78
77
|
{
|
|
79
78
|
path: ['onboarding', 'help'],
|
|
80
79
|
handler: 'commandHelpOnboarding',
|
|
81
|
-
options: ['chains'],
|
|
80
|
+
options: ['chains', 'onboardingHelp'],
|
|
82
81
|
description: 'Structured onboarding help (JSON envelope)',
|
|
83
82
|
},
|
|
84
83
|
{ path: ['wallet', 'list'], handler: 'commandWalletList', description: 'List configured wallets' },
|
|
@@ -113,7 +112,7 @@ export const CLI_MANIFEST = [
|
|
|
113
112
|
path: ['venue', 'setup'],
|
|
114
113
|
handler: 'commandVenueSetup',
|
|
115
114
|
options: ['auth', 'venue'],
|
|
116
|
-
description: 'Prepare or complete venue onboarding
|
|
115
|
+
description: 'Prepare or complete venue onboarding. Thirdfy also runs the one-time setup by itself with the first order (no funds move)',
|
|
117
116
|
args: { query: '<venue>' },
|
|
118
117
|
tier: 'online',
|
|
119
118
|
},
|
|
@@ -121,7 +120,7 @@ export const CLI_MANIFEST = [
|
|
|
121
120
|
path: ['venue', 'fund'],
|
|
122
121
|
handler: 'commandVenueFund',
|
|
123
122
|
options: ['auth', 'venue'],
|
|
124
|
-
description: 'Return venue funding plan
|
|
123
|
+
description: 'Return the venue funding plan. Nothing moves here: each funding step is a write you send with `run` and confirm',
|
|
125
124
|
args: { query: '<venue>' },
|
|
126
125
|
tier: 'online',
|
|
127
126
|
},
|
|
@@ -200,27 +199,6 @@ export const CLI_MANIFEST = [
|
|
|
200
199
|
options: ['auth', 'delegation', 'bootstrap'],
|
|
201
200
|
description: 'Managed wallet + delegation setup',
|
|
202
201
|
},
|
|
203
|
-
{
|
|
204
|
-
path: ['jeff', 'trade'],
|
|
205
|
-
handler: 'commandRun',
|
|
206
|
-
tier: 'online',
|
|
207
|
-
options: ['auth', 'execution'],
|
|
208
|
-
description: 'Execute intent (jeff alias)',
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
path: ['jeff', 'preflight'],
|
|
212
|
-
handler: 'commandPreflight',
|
|
213
|
-
tier: 'online',
|
|
214
|
-
options: ['auth', 'execution'],
|
|
215
|
-
description: 'Governance preflight (jeff alias)',
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
path: ['jeff', 'status'],
|
|
219
|
-
handler: 'commandIntentStatus',
|
|
220
|
-
tier: 'online',
|
|
221
|
-
options: ['execution'],
|
|
222
|
-
description: 'Intent status (jeff alias)',
|
|
223
|
-
},
|
|
224
202
|
{ path: ['catalogs', 'list'], handler: 'commandCatalogsList', tier: 'online', description: 'List action catalogs' },
|
|
225
203
|
{
|
|
226
204
|
path: ['credits', 'balance'],
|
|
@@ -229,6 +207,13 @@ export const CLI_MANIFEST = [
|
|
|
229
207
|
options: ['auth'],
|
|
230
208
|
description: 'Credits balance',
|
|
231
209
|
},
|
|
210
|
+
{
|
|
211
|
+
path: ['credits', 'buy'],
|
|
212
|
+
handler: 'commandCreditsBuy',
|
|
213
|
+
tier: 'online',
|
|
214
|
+
options: ['auth', 'creditsBuy'],
|
|
215
|
+
description: "Buy the agent's Thirdfy credits with USDC from its wallet on Base (gas sponsored): --usd <whole dollars>",
|
|
216
|
+
},
|
|
232
217
|
{
|
|
233
218
|
path: ['credits', 'transactions'],
|
|
234
219
|
handler: 'commandCreditsTransactions',
|
|
@@ -541,6 +526,27 @@ export const CLI_MANIFEST = [
|
|
|
541
526
|
options: ['auth'],
|
|
542
527
|
description: 'Rotate agent API key',
|
|
543
528
|
},
|
|
529
|
+
{
|
|
530
|
+
path: ['wallet-control', 'state'],
|
|
531
|
+
handler: 'commandWalletControlState',
|
|
532
|
+
tier: 'online',
|
|
533
|
+
options: ['auth'],
|
|
534
|
+
description: 'Owner: read the user-owned agent wallet state',
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
path: ['wallet-control', 'request'],
|
|
538
|
+
handler: 'commandWalletControlRequest',
|
|
539
|
+
tier: 'online',
|
|
540
|
+
options: ['auth', 'walletControl'],
|
|
541
|
+
description: 'Owner: get the unsigned request for an owner action (update_policy, stop_agent, resume_agent, change_payout, export)',
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
path: ['wallet-control', 'submit'],
|
|
545
|
+
handler: 'commandWalletControlSubmit',
|
|
546
|
+
tier: 'online',
|
|
547
|
+
options: ['auth', 'walletControl'],
|
|
548
|
+
description: 'Owner: relay the signed owner request',
|
|
549
|
+
},
|
|
544
550
|
{
|
|
545
551
|
path: ['agent', 'key', 'revoke'],
|
|
546
552
|
handler: 'commandAgentKeyRevoke',
|
|
@@ -624,7 +630,7 @@ export const CLI_MANIFEST = [
|
|
|
624
630
|
path: ['actions'],
|
|
625
631
|
handler: 'commandActions',
|
|
626
632
|
tier: 'online',
|
|
627
|
-
options: ['auth', '
|
|
633
|
+
options: ['auth', 'actionList', 'dataCategory'],
|
|
628
634
|
description: 'List allowed actions',
|
|
629
635
|
},
|
|
630
636
|
{
|
|
@@ -634,6 +640,20 @@ export const CLI_MANIFEST = [
|
|
|
634
640
|
options: ['signals'],
|
|
635
641
|
description: 'List data provider apps and the signals they publish (fields, units, freshness, roles, credits)',
|
|
636
642
|
},
|
|
643
|
+
{
|
|
644
|
+
path: ['readiness'],
|
|
645
|
+
handler: 'commandReadiness',
|
|
646
|
+
tier: 'online',
|
|
647
|
+
options: ['auth', 'chains'],
|
|
648
|
+
description: 'Can the agent act? agent_wallet: its execution wallet, funding, gas and wallet control; self/hybrid/thirdfy: the delegation check',
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
path: ['chains'],
|
|
652
|
+
handler: 'commandChains',
|
|
653
|
+
tier: 'online',
|
|
654
|
+
options: ['chainList'],
|
|
655
|
+
description: 'Chains Thirdfy acts on (from the API): chain ids, CAIP-2 ids, execution lanes and the Solana contract',
|
|
656
|
+
},
|
|
637
657
|
{
|
|
638
658
|
path: ['preflight'],
|
|
639
659
|
handler: 'commandPreflight',
|
|
@@ -641,6 +661,13 @@ export const CLI_MANIFEST = [
|
|
|
641
661
|
options: ['auth', 'execution'],
|
|
642
662
|
description: 'Governance preflight',
|
|
643
663
|
},
|
|
664
|
+
{
|
|
665
|
+
path: ['preview'],
|
|
666
|
+
handler: 'commandPreview',
|
|
667
|
+
tier: 'online',
|
|
668
|
+
options: ['auth', 'execution'],
|
|
669
|
+
description: 'Preview a write (agent_wallet): would Thirdfy sign it, order and risk preview, and the run command. Nothing is sent',
|
|
670
|
+
},
|
|
644
671
|
{ path: ['run'], handler: 'commandRun', tier: 'online', options: ['auth', 'execution'], description: 'Execute intent' },
|
|
645
672
|
{
|
|
646
673
|
path: ['self-exec'],
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Commander 13+ rejects multi-character short flags; keep the historical `-ni` spelling working, and
|
|
3
|
+
* `--ni`, the spelling the README and onboarding help use.
|
|
4
|
+
*/
|
|
5
|
+
const NOT_INTERACTIVE_ALIASES = new Set(['-ni', '--ni']);
|
|
6
|
+
|
|
2
7
|
export function normalizeLegacyShortFlags(argv) {
|
|
3
8
|
const end = argv.indexOf('--');
|
|
4
|
-
return argv.map((arg, index) => (arg
|
|
9
|
+
return argv.map((arg, index) => (NOT_INTERACTIVE_ALIASES.has(arg) && (end === -1 || index < end) ? '--not-interactive' : arg));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** `help onboarding --path`: one path, as thirdfy-mcp `describeOnboardingPath`. */
|
|
13
|
+
export function attachOnboardingHelpOptions(cmd) {
|
|
14
|
+
return cmd.option('--path <id>', 'one path: email_otp | wallet_sign | existing_credentials | mcp_bootstrap | all');
|
|
5
15
|
}
|
|
6
16
|
|
|
7
17
|
export function attachBootstrapOptions(cmd) {
|
|
@@ -16,9 +26,11 @@ export function attachBootstrapOptions(cmd) {
|
|
|
16
26
|
.option('--otp <otp>', 'email OTP alias')
|
|
17
27
|
.option('--accept-terms', 'accept terms for email login')
|
|
18
28
|
.option('--key-name <name>', 'Privy key name')
|
|
19
|
-
.option('--not-interactive', 'fail fast when required login input is missing (
|
|
29
|
+
.option('--not-interactive', 'fail fast when required login input is missing (aliases: --ni, -ni)')
|
|
20
30
|
.option('--no-bootstrap-agent', 'skip agent bootstrap on email login')
|
|
21
31
|
.option('--rotate-agent-key', 'rotate agent key')
|
|
32
|
+
.option('--owner-payout-address <addr>', 'owner payout address for exits from a wallet under wallet control (API 4.0+)')
|
|
33
|
+
.option('--allowed-actions <list>', "comma-separated catalog action names for the agent's action template (API 4.0+)")
|
|
22
34
|
.option('--login-attempt-id <id>', 'email login attempt id')
|
|
23
35
|
.option('--all', 'logout all sessions')
|
|
24
36
|
.option('--clear-agent-key', 'clear stored agent key on logout');
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
export function attachChainOptions(cmd) {
|
|
2
2
|
return cmd.option('--chain-id <id>', 'chain id');
|
|
3
3
|
}
|
|
4
|
+
|
|
5
|
+
/** Options for `chains` (thirdfy-mcp getChainCapabilities / getNonEvmCapabilities). */
|
|
6
|
+
export function attachChainListOptions(cmd) {
|
|
7
|
+
return cmd.option('--non-evm', 'only the non-EVM (Solana) execution contract');
|
|
8
|
+
}
|
|
@@ -13,3 +13,12 @@ export function attachCreditsOptions(cmd) {
|
|
|
13
13
|
)
|
|
14
14
|
.option('--surface <surface>', 'billing surface (console, automation, cli, agent_api)', 'cli');
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
/** `credits buy` only: no catalog or pricing flags, and no --action / --params to override. */
|
|
18
|
+
export function attachCreditsBuyOptions(cmd) {
|
|
19
|
+
return cmd
|
|
20
|
+
.option('--usd <dollars>', 'whole US dollars of credits to buy with USDC from the agent wallet')
|
|
21
|
+
.option('--tx-hash <hash>', 'resume a purchase whose USDC payment was already sent (after WRITE_OUTCOME_UNKNOWN)')
|
|
22
|
+
.option('--chain-id <id>', 'chain the USDC is paid on (default 8453 Base; 84532 Base Sepolia on test APIs)')
|
|
23
|
+
.option('--idempotency-key <key>', 'idempotency key for this purchase');
|
|
24
|
+
}
|
package/src/cli/options/data.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Options of the data commands: `
|
|
1
|
+
/** Options of the discovery and data commands: `actions` filters and `signals`. */
|
|
2
2
|
|
|
3
3
|
export function attachSignalsOptions(cmd) {
|
|
4
4
|
return cmd
|
|
@@ -12,3 +12,15 @@ export function attachDataCategoryOptions(cmd) {
|
|
|
12
12
|
'only data reads of this category (market_data, signal, research, wallet); comma-separated for several',
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
|
+
|
|
16
|
+
/** `actions` filters. It lists actions only, so it takes none of the `run` / `preflight` options. */
|
|
17
|
+
export function attachActionListOptions(cmd) {
|
|
18
|
+
return cmd
|
|
19
|
+
.option('--provider <id>', 'only this provider (hyperliquid, polymarket, earn, ...)')
|
|
20
|
+
.option('--chain-id <id>', 'only actions on this chain')
|
|
21
|
+
.option('--catalog <id>', 'only this actions catalog')
|
|
22
|
+
.option('--search <text>', 'only actions whose name, description or aliases contain this text (one page)')
|
|
23
|
+
.option('--limit <n>', 'page size (concise: 50 by default, at most 100; detailed: 10, at most 25)')
|
|
24
|
+
.option('--offset <n>', 'skip this many matching actions (default 0)')
|
|
25
|
+
.option('--view <view>', 'concise (default with paging) or detailed (full entries with paramsSchema)');
|
|
26
|
+
}
|
|
@@ -4,20 +4,21 @@ import { attachExecutionOptions } from './execution.mjs';
|
|
|
4
4
|
import { attachDelegationOptions } from './delegation.mjs';
|
|
5
5
|
import { attachTrackingOptions } from './tracking.mjs';
|
|
6
6
|
import { attachWalletOptions } from './wallet.mjs';
|
|
7
|
-
import { attachBootstrapOptions } from './bootstrap.mjs';
|
|
7
|
+
import { attachBootstrapOptions, attachOnboardingHelpOptions } from './bootstrap.mjs';
|
|
8
8
|
import { attachCredentialsOptions } from './credentials.mjs';
|
|
9
9
|
import { attachAnalyticsOptions } from './analytics.mjs';
|
|
10
10
|
import { attachPolymarketOptions } from './polymarket.mjs';
|
|
11
11
|
import { attachHummingbotOptions } from './hummingbot.mjs';
|
|
12
12
|
import { attachCondorOptions } from './condor.mjs';
|
|
13
13
|
import { attachAgentRegisterOptions } from './agent.mjs';
|
|
14
|
-
import { attachChainOptions } from './chains.mjs';
|
|
15
|
-
import { attachCreditsOptions } from './credits.mjs';
|
|
14
|
+
import { attachChainListOptions, attachChainOptions } from './chains.mjs';
|
|
15
|
+
import { attachCreditsBuyOptions, attachCreditsOptions } from './credits.mjs';
|
|
16
16
|
import { attachChatOptions } from './chat.mjs';
|
|
17
17
|
import { attachVenueOptions } from './venue.mjs';
|
|
18
18
|
import { attachBrainOptions } from './brain.mjs';
|
|
19
19
|
import { attachCertificationOptions } from './certification.mjs';
|
|
20
|
-
import { attachDataCategoryOptions, attachSignalsOptions } from './data.mjs';
|
|
20
|
+
import { attachActionListOptions, attachDataCategoryOptions, attachSignalsOptions } from './data.mjs';
|
|
21
|
+
import { attachWalletControlOptions } from './walletControl.mjs';
|
|
21
22
|
|
|
22
23
|
const BUNDLES = {
|
|
23
24
|
auth: attachAuthOptions,
|
|
@@ -26,6 +27,7 @@ const BUNDLES = {
|
|
|
26
27
|
tracking: attachTrackingOptions,
|
|
27
28
|
wallet: attachWalletOptions,
|
|
28
29
|
bootstrap: attachBootstrapOptions,
|
|
30
|
+
onboardingHelp: attachOnboardingHelpOptions,
|
|
29
31
|
credentials: attachCredentialsOptions,
|
|
30
32
|
analytics: attachAnalyticsOptions,
|
|
31
33
|
polymarket: attachPolymarketOptions,
|
|
@@ -33,13 +35,17 @@ const BUNDLES = {
|
|
|
33
35
|
condor: attachCondorOptions,
|
|
34
36
|
agent: attachAgentRegisterOptions,
|
|
35
37
|
chains: attachChainOptions,
|
|
38
|
+
chainList: attachChainListOptions,
|
|
36
39
|
credits: attachCreditsOptions,
|
|
40
|
+
creditsBuy: attachCreditsBuyOptions,
|
|
37
41
|
chat: attachChatOptions,
|
|
38
42
|
venue: attachVenueOptions,
|
|
39
43
|
brain: attachBrainOptions,
|
|
40
44
|
certification: attachCertificationOptions,
|
|
41
45
|
signals: attachSignalsOptions,
|
|
42
46
|
dataCategory: attachDataCategoryOptions,
|
|
47
|
+
actionList: attachActionListOptions,
|
|
48
|
+
walletControl: attachWalletControlOptions,
|
|
43
49
|
};
|
|
44
50
|
|
|
45
51
|
/** @param {import('commander').Command} cmd */
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Options of `wallet-control request|submit` (owner actions on a user-owned agent wallet). */
|
|
2
|
+
export function attachWalletControlOptions(cmd) {
|
|
3
|
+
return cmd
|
|
4
|
+
.option('--action <action>', 'owner action: update_policy, stop_agent, resume_agent, change_payout, export')
|
|
5
|
+
.option('--payout-address <addr>', 'new owner payout address (change_payout)')
|
|
6
|
+
.option('--recipient-public-key <key>', 'HPKE recipient public key (export)')
|
|
7
|
+
.option('--signature-input <json>', 'the signatureInput of the request the owner signed (submit)');
|
|
8
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { requireFlag, isNonInteractive } from '../core/args.mjs';
|
|
1
|
+
import { requireFlag, isNonInteractive, usageError } from '../core/args.mjs';
|
|
2
2
|
import { createCliError } from '../core/envelope.mjs';
|
|
3
3
|
import { PROFILE_DEFAULTS } from '../core/constants.mjs';
|
|
4
4
|
import {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
getProfileConfigPath,
|
|
17
17
|
} from '../core/context.mjs';
|
|
18
18
|
import { apiGet, apiPost, requestWithRouteFallback } from '../core/http.mjs';
|
|
19
|
+
import { isEvmAddress, isSolanaAddress } from '../core/chainRegistry.mjs';
|
|
19
20
|
import { createRequire } from 'module';
|
|
20
21
|
|
|
21
22
|
const require = createRequire(import.meta.url);
|
|
@@ -153,12 +154,24 @@ async function commandConfigSet(ctx, flags) {
|
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
|
|
157
|
+
const ONBOARDING_PATHS = ['email_otp', 'wallet_sign', 'existing_credentials', 'mcp_bootstrap'];
|
|
158
|
+
|
|
159
|
+
/** `help onboarding [--path <id>]`: every path, or one with `selectedPath` (thirdfy-mcp `describeOnboardingPath`). */
|
|
156
160
|
async function commandHelpOnboarding(ctx, flags) {
|
|
161
|
+
const help = buildOnboardingHelp(ctx, flags);
|
|
162
|
+
const selectedPath = String(flags.path || 'all').trim().toLowerCase();
|
|
163
|
+
if (selectedPath !== 'all' && !ONBOARDING_PATHS.includes(selectedPath)) {
|
|
164
|
+
throw usageError(`--path must be one of ${ONBOARDING_PATHS.join(', ')} or all`, 'path');
|
|
165
|
+
}
|
|
166
|
+
const data =
|
|
167
|
+
selectedPath === 'all'
|
|
168
|
+
? { selectedPath, ...help }
|
|
169
|
+
: { selectedPath, ...help.paths.find((entry) => entry.id === selectedPath), nonInteractive: help.nonInteractive, gas: help.gas, apiBase: help.apiBase };
|
|
157
170
|
printEnvelope({
|
|
158
171
|
success: true,
|
|
159
172
|
code: 'ONBOARDING_HELP_OK',
|
|
160
|
-
message: 'Thirdfy onboarding help'
|
|
161
|
-
data
|
|
173
|
+
message: selectedPath === 'all' ? 'Thirdfy onboarding help' : `Thirdfy onboarding help: ${selectedPath}`,
|
|
174
|
+
data,
|
|
162
175
|
meta: { apiBase: ctx.apiBase },
|
|
163
176
|
});
|
|
164
177
|
}
|
|
@@ -289,6 +302,16 @@ async function commandLogin(ctx, flags) {
|
|
|
289
302
|
|
|
290
303
|
let bootstrapAgentApiKey = '';
|
|
291
304
|
let bootstrapPerformed = false;
|
|
305
|
+
// API 4.0: where exits from a wallet under wallet control may pay, and the agent's action
|
|
306
|
+
// template. The API validates both and answers ownerPayout / actionTemplate (thirdfy-mcp
|
|
307
|
+
// bootstrapSelfIdentity parity).
|
|
308
|
+
const ownerPayoutAddress = String(flags.ownerPayoutAddress || '').trim();
|
|
309
|
+
const allowedActions = String(flags.allowedActions || '')
|
|
310
|
+
.split(',')
|
|
311
|
+
.map((entry) => entry.trim())
|
|
312
|
+
.filter(Boolean);
|
|
313
|
+
let ownerPayout;
|
|
314
|
+
let actionTemplate;
|
|
292
315
|
const requestedAgentApiKey = String(flags.agentApiKey || '').trim();
|
|
293
316
|
const bootstrapAgentKey = String(flags.agentKey || '').trim();
|
|
294
317
|
if (!requestedAgentApiKey && bootstrapAgentKey) {
|
|
@@ -308,11 +331,15 @@ async function commandLogin(ctx, flags) {
|
|
|
308
331
|
custodyMode,
|
|
309
332
|
...(flags.walletAddress ? { walletAddress: String(flags.walletAddress).trim() } : {}),
|
|
310
333
|
rotate: parseBooleanFlag(flags.rotateAgentKey, false),
|
|
334
|
+
...(ownerPayoutAddress ? { ownerPayoutAddress } : {}),
|
|
335
|
+
...(allowedActions.length ? { allowedActions } : {}),
|
|
311
336
|
},
|
|
312
337
|
});
|
|
313
338
|
bootstrapAgentApiKey = String(
|
|
314
339
|
bootstrapResponse?.agentApiKey || bootstrapResponse?.data?.agentApiKey || ''
|
|
315
340
|
).trim();
|
|
341
|
+
ownerPayout = bootstrapResponse?.ownerPayout || bootstrapResponse?.data?.ownerPayout;
|
|
342
|
+
actionTemplate = bootstrapResponse?.actionTemplate || bootstrapResponse?.data?.actionTemplate;
|
|
316
343
|
bootstrapPerformed = true;
|
|
317
344
|
}
|
|
318
345
|
}
|
|
@@ -355,6 +382,8 @@ async function commandLogin(ctx, flags) {
|
|
|
355
382
|
hasOwnerSessionToken: Boolean(ownerSessionToken),
|
|
356
383
|
hasAgentApiKey: Boolean(requestedAgentApiKey || bootstrapAgentApiKey),
|
|
357
384
|
bootstrapPerformed,
|
|
385
|
+
...(ownerPayout ? { ownerPayout } : {}),
|
|
386
|
+
...(actionTemplate ? { actionTemplate } : {}),
|
|
358
387
|
runMode: loginRunMode,
|
|
359
388
|
custodyMode,
|
|
360
389
|
configPath: getProfileConfigPath(),
|
|
@@ -499,12 +528,15 @@ async function commandLoginEmail(ctx, flags) {
|
|
|
499
528
|
// Persist first so operators keep session tokens even when wallet provisioning failed.
|
|
500
529
|
persistProfileConfig(next);
|
|
501
530
|
|
|
531
|
+
// An EVM (0x) or Solana (base58) execution wallet counts; an agent may have only a Solana one.
|
|
502
532
|
const executionWalletAddresses = Object.values(executionWallets)
|
|
503
533
|
.map((row) => (row && typeof row === 'object' ? String(row.walletAddress || '').trim() : ''))
|
|
504
|
-
.filter((addr) =>
|
|
534
|
+
.filter((addr) => isEvmAddress(addr) || isSolanaAddress(addr));
|
|
505
535
|
const hasExecutionWallet = executionWalletAddresses.length > 0;
|
|
506
536
|
if (runMode === 'agent_wallet' && (executionWalletsError || !hasExecutionWallet)) {
|
|
507
|
-
const fundHint = executionWalletAddresses
|
|
537
|
+
const fundHint = executionWalletAddresses.length
|
|
538
|
+
? executionWalletAddresses.join(', ')
|
|
539
|
+
: 'the managed execution wallet address for each chain';
|
|
508
540
|
throw createCliError(
|
|
509
541
|
'LOGIN_EMAIL_INCOMPLETE',
|
|
510
542
|
executionWalletsError
|
|
@@ -538,6 +570,13 @@ async function commandLoginEmail(ctx, flags) {
|
|
|
538
570
|
? {
|
|
539
571
|
fundingReminder:
|
|
540
572
|
'Fund executionWallets addresses for agent_wallet. Do not fund the owner embedded wallet for Path A trading.',
|
|
573
|
+
...(executionWalletAddresses.some((addr) => isSolanaAddress(addr))
|
|
574
|
+
? {
|
|
575
|
+
solanaFundingReminder: `Fund the Solana execution wallet ${executionWalletAddresses
|
|
576
|
+
.filter((addr) => isSolanaAddress(addr))
|
|
577
|
+
.join(', ')} (base58; give the user this address, not the EVM one) with the SPL tokens (such as USDC) the agent trades. Thirdfy sponsors Solana network fees; keep a little SOL only for rent on new token accounts (about 0.002 SOL each).`,
|
|
578
|
+
}
|
|
579
|
+
: {}),
|
|
541
580
|
}
|
|
542
581
|
: {}),
|
|
543
582
|
},
|
package/src/commands/chat.mjs
CHANGED
|
@@ -16,6 +16,9 @@ const NETWORK_CHAIN_IDS = {
|
|
|
16
16
|
'arc-testnet': 5042002,
|
|
17
17
|
'arc-mainnet': 5042,
|
|
18
18
|
'arc': 5042,
|
|
19
|
+
// Solana (svm). Without these, --network sol-mainnet fell through to the Base default.
|
|
20
|
+
'sol-mainnet': 101,
|
|
21
|
+
'sol-devnet': 103,
|
|
19
22
|
};
|
|
20
23
|
|
|
21
24
|
const DEFAULT_CHAT_CHAIN_ID = 8453;
|
package/src/commands/credits.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { requireFlag } from '../core/args.mjs';
|
|
1
|
+
import { requireFlag, usageError } from '../core/args.mjs';
|
|
2
2
|
import { apiGet, apiPost } from '../core/http.mjs';
|
|
3
3
|
import { toAvantisSpelling } from '../core/venueBrand.mjs';
|
|
4
4
|
import {
|
|
5
5
|
formatCreditsEstimateSummary,
|
|
6
6
|
formatCreditsModelsSummary,
|
|
7
|
+
stripUsdFields,
|
|
7
8
|
} from '../lib/creditsUsdSummary.mjs';
|
|
8
9
|
|
|
9
10
|
function resolveToolCallsEstimate(flags) {
|
|
@@ -32,7 +33,38 @@ function resolveToolCallsEstimate(flags) {
|
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
/** Thirdfy credits are bought on Base with USDC from the agent's wallet (thirdfy-api-v2 `buy-agent-credits`). */
|
|
37
|
+
const CREDITS_PURCHASE_CHAIN_ID = 8453;
|
|
38
|
+
|
|
39
|
+
export function createCreditsCommands({ printEnvelope, getAuthToken, commandWalletExecute }) {
|
|
40
|
+
/**
|
|
41
|
+
* `credits buy --usd <n>`: buy the agent's Thirdfy credits with USDC from its execution wallet on
|
|
42
|
+
* Base (gas sponsored), as thirdfy-mcp's `walletExecute buy-agent-credits` does. A shortcut for
|
|
43
|
+
* `wallet execute --action buy-agent-credits --params '{"usdAmount":n}' --chain-id 8453`; the API
|
|
44
|
+
* sets the allowed range (whole dollars, $2 to $1,000 today). A purchase whose claim did not
|
|
45
|
+
* finish answers WRITE_OUTCOME_UNKNOWN: check `credits balance`, do not buy again; `--tx-hash`
|
|
46
|
+
* resumes that purchase without paying twice. `--chain-id` defaults to Base (84532 on test APIs).
|
|
47
|
+
*/
|
|
48
|
+
async function commandCreditsBuy(ctx, flags, capabilities) {
|
|
49
|
+
const raw = String(requireFlag(flags, 'usd', 'Missing --usd (whole US dollars, for example --usd 10)')).trim();
|
|
50
|
+
if (!/^\d+$/.test(raw) || Number(raw) <= 0) throw usageError('--usd must be a whole number of US dollars, for example 10', 'usd');
|
|
51
|
+
const usdAmount = Number(raw);
|
|
52
|
+
const txHash = String(flags.txHash || '').trim();
|
|
53
|
+
await commandWalletExecute(
|
|
54
|
+
ctx,
|
|
55
|
+
{
|
|
56
|
+
...flags,
|
|
57
|
+
action: 'buy-agent-credits',
|
|
58
|
+
// txHash resumes a purchase whose payment was already sent (the catalog row takes it).
|
|
59
|
+
params: JSON.stringify({ usdAmount, ...(txHash ? { txHash } : {}) }),
|
|
60
|
+
chainId: String(flags.chainId || CREDITS_PURCHASE_CHAIN_ID),
|
|
61
|
+
estimatedAmountUsd: String(usdAmount),
|
|
62
|
+
runMode: 'agent_wallet',
|
|
63
|
+
},
|
|
64
|
+
capabilities,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
36
68
|
async function commandCreditsTransactions(ctx, flags) {
|
|
37
69
|
const authToken = getAuthToken(flags, 'Missing --auth-token (or THIRDFY_AUTH_TOKEN) for credits transactions');
|
|
38
70
|
const page = Number(flags.page || 1);
|
|
@@ -127,13 +159,16 @@ export function createCreditsCommands({ printEnvelope, getAuthToken }) {
|
|
|
127
159
|
printEnvelope({
|
|
128
160
|
success: true,
|
|
129
161
|
code: 'OK',
|
|
130
|
-
|
|
131
|
-
|
|
162
|
+
// wouldBePaidBy (agent_credits | free_request | owner_credits | none), when the API sends it.
|
|
163
|
+
message: response?.wouldBePaidBy ? `Action pricing quote generated; would be paid by ${response.wouldBePaidBy}` : 'Action pricing quote generated',
|
|
164
|
+
// An action's cost is in credits only, never dollars (thirdfy-mcp quoteActionPricing).
|
|
165
|
+
data: stripUsdFields(response),
|
|
132
166
|
meta: { apiBase: ctx.apiBase, action },
|
|
133
167
|
});
|
|
134
168
|
}
|
|
135
169
|
|
|
136
170
|
return {
|
|
171
|
+
commandCreditsBuy,
|
|
137
172
|
commandCreditsTransactions,
|
|
138
173
|
commandCreditsUsage,
|
|
139
174
|
commandModelsList,
|
|
@@ -426,9 +426,11 @@ async function commandDelegationRedeem(ctx, flags, capabilities) {
|
|
|
426
426
|
if (!['thirdfy', 'hybrid', 'agent_wallet'].includes(selectedRunMode)) {
|
|
427
427
|
throw createCliError('DELEGATION_REDEEM_MODE_INVALID', 'delegation redeem supports only --run-mode thirdfy|hybrid|agent_wallet');
|
|
428
428
|
}
|
|
429
|
+
// Pass the run mode on only when it was given: a profile / config default must still be able to
|
|
430
|
+
// switch to agent_wallet on a Solana action (commandRun resolves the effective mode itself).
|
|
429
431
|
const delegatedFlags = {
|
|
430
432
|
...flags,
|
|
431
|
-
runMode: selectedRunMode,
|
|
433
|
+
...(flags.runMode ? { runMode: selectedRunMode } : {}),
|
|
432
434
|
};
|
|
433
435
|
if (!delegatedFlags.estimatedAmountUsd) {
|
|
434
436
|
delegatedFlags.estimatedAmountUsd = '5';
|