@thirdfy/agent-cli 0.2.71 → 0.2.73

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 CHANGED
@@ -4,6 +4,22 @@ All notable changes to `@thirdfy/agent-cli` are documented here. The format is b
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.2.73] - 2026-09-21
8
+
9
+ ### Added
10
+
11
+ - Hyperliquid Circle CCTP ids: `quote_hyperliquid_cctp_deposit` (read) and `deposit_hyperliquid_cctp` (write, 180s timeout). Managed execute signs those on `params.sourceChainId` and fails closed without it. Provider hints follow API `setupHints` and `get_hyperliquid_funding_status` `nextAction` instead of hardcoded Arbitrum / Li.Fi. Pin: `test/walletExecuteChainId.test.cjs`, `test/read-only-action-classifier.test.cjs`. Pairs with `thirdfy-mcp` **0.0.123**.
12
+
13
+ ### Fixed
14
+
15
+ - Managed execute signs `execute_bridge` / `get_bridge_quote` on `params.fromChain` even when `--chain-id` defaulted to Base. Preflight uses the same chain resolver as the execute payload. `execute_bridge`, `get_bridge_quote`, and `swap` use the 180s timeout. Pin: `test/walletExecuteChainId.test.cjs`, `test/actionTimeouts.test.cjs`. Pairs with `thirdfy-mcp` **0.0.123**.
16
+
17
+ ## [0.2.72] - 2026-09-17
18
+
19
+ ### Added
20
+
21
+ - Hyperliquid `place_hyperliquid_tp_sl` certification fixture, write lane, and provider hint. Lighter `place_lighter_perps_order` `orderType` enum includes `stop_loss`, `stop_loss_limit`, `take_profit`, `take_profit_limit`. Pin: `test/read-only-action-classifier.test.cjs`. Pairs with `thirdfy-mcp` **0.0.122** and Thirdfy API **3.14.50**.
22
+
7
23
  ## [0.2.71] - 2026-09-16
8
24
 
9
25
  ### Fixed
package/README.md CHANGED
@@ -40,10 +40,10 @@ Run without global install:
40
40
  npx @thirdfy/agent-cli --help
41
41
  ```
42
42
 
43
- ## What's new in v0.2.71
43
+ ## What's new in v0.2.73
44
44
 
45
- - Avantis setup-status and onboarding-plan reads wait for the compose timeout instead of falling back early.
46
- - An empty queued execute-intent fallback fails instead of looking like a successful empty setup payload.
45
+ - Hyperliquid Circle CCTP ids `quote_hyperliquid_cctp_deposit` and `deposit_hyperliquid_cctp`. Managed execute signs those on `params.sourceChainId` with no default chain.
46
+ - Provider hints follow API `setupHints` and `get_hyperliquid_funding_status` `nextAction` instead of hardcoded Arbitrum / Li.Fi.
47
47
  - See [CHANGELOG.md](./CHANGELOG.md) and GitHub Releases for older versions.
48
48
 
49
49
  ## Quick start
@@ -198,7 +198,7 @@ Auth expectations by mode:
198
198
  - `hybrid`: requires execution identity and governed mirror semantics (`--hybrid-wallet-mode self|agent_wallet`, default `self`).
199
199
  - `thirdfy`: requires execution identity and delegated governance path.
200
200
  - `agent_wallet`: requires execution identity and owner `userDid`, but does not require subscriber delegation when the owner identity matches the agent wallet/creator. Thirdfy credits/free quota still gate execution; Privy gas sponsorship only covers network gas when enabled.
201
- - Hyperliquid setup uses `complete_hyperliquid_onboarding` for runtime-owned funding/setup. It can submit Li.Fi and Bridge2 steps automatically, then return `bridge2_submitted` while Hyperliquid credits the deposit. Bridge2 setup is the Arbitrum exception to the Base-focused `agent_wallet` rule: Bridge2 credits the transaction sender. Pass **`--estimated-amount-usd`** as a top-level flag (not inside `--params`). The normal solo `agent_wallet` path uses the managed execution wallet as the Hyperliquid main wallet. If margin already sits on a different Hyperliquid main wallet, pass that wallet as `mainWalletAddress` / order `userAddress`, and pass the approved execution/API wallet as `apiWalletAddress`. When USDC sits on your linked email-login wallet (`primaryEvmWallet`) instead of the managed execution wallet, Thirdfy API returns **`FUND_AGENT_EXECUTION_WALLET`** / **`MANUAL_BRIDGE2_DEPOSIT_REQUIRED`** with `fundedWallet` and `executionWalletAddress`; move native Arbitrum USDC to `executionWalletAddress` and retry.
201
+ - Hyperliquid setup uses `complete_hyperliquid_onboarding` for runtime-owned funding/setup. Call `get_hyperliquid_funding_status` and follow `nextAction` plus `nextActionParams`. Do not invent a funding chain. Pass **`--estimated-amount-usd`** as a top-level flag (not inside `--params`). The normal solo `agent_wallet` path uses the managed execution wallet as the Hyperliquid main wallet. If margin already sits on a different Hyperliquid main wallet, pass that wallet as `mainWalletAddress` / order `userAddress`, and pass the approved execution/API wallet as `apiWalletAddress`. When USDC sits on your linked email-login wallet (`primaryEvmWallet`) instead of the managed execution wallet, Thirdfy API returns **`FUND_AGENT_EXECUTION_WALLET`** with `fundedWallet` and `executionWalletAddress`; move USDC to `executionWalletAddress` on the chain named by `nextActionParams.sourceChainId` and retry.
202
202
  - custody mode defaults are profile-aware:
203
203
  - `managed` default for `thirdfy`
204
204
  - `external` default for `self` and `hybrid`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdfy/agent-cli",
3
- "version": "0.2.71",
3
+ "version": "0.2.73",
4
4
  "description": "Thirdfy Agent CLI for onboarding, governance preflight, execute-intent, and status polling.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,6 +16,11 @@ const LONG_RUNNING_ACTIONS = new Set([
16
16
  'get_cmc_perp_contract_analysis',
17
17
  'get_cmc_market_regime',
18
18
  'get_cmc_derivatives_crowding',
19
+ 'execute_bridge',
20
+ 'get_bridge_quote',
21
+ 'swap',
22
+ 'execute_optimal_swap',
23
+ 'deposit_hyperliquid_cctp',
19
24
  ]);
20
25
 
21
26
  function normalizeActionId(action) {
@@ -20,6 +20,7 @@ const READ_ONLY_EXACT = new Set([
20
20
  'get_condor_policy_status',
21
21
  'get_hummingbot_gateway_networks',
22
22
  'get_hummingbot_gateway_connectors',
23
+ 'quote_hyperliquid_cctp_deposit',
23
24
  ]);
24
25
 
25
26
  export function normalizeActionKey(actionKey) {
@@ -0,0 +1,49 @@
1
+ const DEFAULT_CHAIN_ID = 8453;
2
+
3
+ function normalizeActionId(action) {
4
+ return String(action || '')
5
+ .trim()
6
+ .replace(/-/g, '_')
7
+ .toLowerCase();
8
+ }
9
+
10
+ function positiveChainId(value) {
11
+ const n = Number(value);
12
+ if (!Number.isFinite(n) || n <= 0) return undefined;
13
+ return Math.trunc(n);
14
+ }
15
+
16
+ function isBridgeAction(action) {
17
+ const key = normalizeActionId(action);
18
+ return key === 'execute_bridge' || key === 'get_bridge_quote' || key === 'check_bridge_status';
19
+ }
20
+
21
+ function isHyperliquidCctpAction(action) {
22
+ const key = normalizeActionId(action);
23
+ return key === 'deposit_hyperliquid_cctp' || key === 'quote_hyperliquid_cctp_deposit';
24
+ }
25
+
26
+ /**
27
+ * Signing / wallet-preflight chain for managed execute.
28
+ * Bridge writes sign on fromChain. CCTP burns sign on sourceChainId. Do not default Base.
29
+ */
30
+ export function resolveWalletExecuteChainId({ action, chainId, params } = {}) {
31
+ const record = params && typeof params === 'object' ? params : {};
32
+ if (isHyperliquidCctpAction(action)) {
33
+ const sourceChainId = positiveChainId(record.sourceChainId);
34
+ if (!sourceChainId) {
35
+ throw new Error('HYPERLIQUID_CCTP_SOURCE_CHAIN_REQUIRED');
36
+ }
37
+ return sourceChainId;
38
+ }
39
+ if (isBridgeAction(action)) {
40
+ return (
41
+ positiveChainId(record.fromChain) ||
42
+ positiveChainId(record.fromChainId) ||
43
+ positiveChainId(chainId) ||
44
+ positiveChainId(record.chainId) ||
45
+ DEFAULT_CHAIN_ID
46
+ );
47
+ }
48
+ return positiveChainId(chainId) || positiveChainId(record.chainId) || DEFAULT_CHAIN_ID;
49
+ }
@@ -93,6 +93,8 @@ function inferActionProvider(action) {
93
93
  'get-hyperliquid-referral-status': 'hyperliquid',
94
94
  'deposit-hyperliquid-staking': 'hyperliquid',
95
95
  'deposit-hyperliquid-bridge': 'hyperliquid',
96
+ 'deposit-hyperliquid-cctp': 'hyperliquid',
97
+ 'quote-hyperliquid-cctp-deposit': 'hyperliquid',
96
98
  'place-hyperliquid-perps-order': 'hyperliquid',
97
99
  'cancel-hyperliquid-perps-order': 'hyperliquid',
98
100
  'update-hyperliquid-leverage': 'hyperliquid',
@@ -47,6 +47,37 @@ export const VENUE_WRITE_ACTION_FIXTURES = [
47
47
  },
48
48
  validSample: { coin: 'ETH', orderId: 1 },
49
49
  },
50
+ {
51
+ action: 'place_hyperliquid_tp_sl',
52
+ aliases: ['place-hyperliquid-tp-sl'],
53
+ provider: 'hyperliquid',
54
+ authorityInputs: ['agentApiKey', 'estimatedAmountUsd'],
55
+ paramsSchema: {
56
+ type: 'object',
57
+ additionalProperties: false,
58
+ required: ['coin', 'tpsl', 'triggerPx', 'size', 'isBuy'],
59
+ properties: {
60
+ coin: { type: 'string', minLength: 1 },
61
+ tpsl: { type: 'string', enum: ['tp', 'sl'] },
62
+ triggerPx: { type: 'number', minimum: 0 },
63
+ isMarket: { type: 'boolean' },
64
+ limitPx: { type: 'number', minimum: 0 },
65
+ size: { type: 'number', minimum: 0 },
66
+ isBuy: { type: 'boolean' },
67
+ reduceOnly: { type: 'boolean' },
68
+ grouping: { type: 'string', enum: ['na', 'normalTpsl', 'positionTpsl'] },
69
+ userAddress: { type: 'string' },
70
+ },
71
+ },
72
+ validSample: {
73
+ coin: 'ETH',
74
+ tpsl: 'sl',
75
+ triggerPx: 3000,
76
+ size: 0.01,
77
+ isBuy: false,
78
+ reduceOnly: true,
79
+ },
80
+ },
50
81
  {
51
82
  action: 'update_hyperliquid_leverage',
52
83
  aliases: ['update-hyperliquid-leverage'],
@@ -82,7 +113,11 @@ export const VENUE_WRITE_ACTION_FIXTURES = [
82
113
  baseAmount: { type: 'integer', minimum: 1 },
83
114
  price: { type: 'integer', minimum: 1 },
84
115
  isAsk: { type: 'boolean' },
85
- orderType: { type: 'string', enum: ['limit', 'market'] },
116
+ orderType: {
117
+ type: 'string',
118
+ enum: ['limit', 'market', 'stop_loss', 'stop_loss_limit', 'take_profit', 'take_profit_limit'],
119
+ },
120
+ triggerPrice: { type: 'integer', minimum: 1 },
86
121
  reduceOnly: { type: 'boolean' },
87
122
  },
88
123
  },
@@ -3,6 +3,8 @@ export function createExecutionLanes() {
3
3
  const OFFCHAIN_VENUE_ORDER_ACTIONS = new Set([
4
4
  'place_hyperliquid_perps_order',
5
5
  'place-hyperliquid-perps-order',
6
+ 'place_hyperliquid_tp_sl',
7
+ 'place-hyperliquid-tp-sl',
6
8
  'cancel_hyperliquid_perps_order',
7
9
  'cancel-hyperliquid-perps-order',
8
10
  'update_hyperliquid_leverage',
@@ -7,6 +7,7 @@ import { createCliError } from '../../core/envelope.mjs';
7
7
  import { normalizeRunMode, normalizeManagedRunMode, normalizeHybridWalletMode } from '../../core/runMode.mjs';
8
8
  import { assertHostedRuntimePolymarketWriteIdempotency } from './hostedRuntimeWriteGate.mjs';
9
9
  import { resolveTokenInForFunding } from '../../core/fundingTokenIn.mjs';
10
+ import { resolveWalletExecuteChainId } from '../../core/walletExecuteChainId.mjs';
10
11
 
11
12
  function isTruthyFlag(value) {
12
13
  return value === true || String(value || '').trim().toLowerCase() === 'true';
@@ -129,16 +130,21 @@ function buildManagedExecutePayload(flags, options) {
129
130
  delete managedParams.tokenInDecimals;
130
131
  managedParams.amountIn = flags.__swapInput.amountInHuman;
131
132
  }
133
+ const action = String(options.resolvedAction || requireFlag(flags, 'action', 'Missing --action')).trim();
132
134
  const payload = {
133
135
  agentApiKey: resolveAgentApiKey(flags, runMode),
134
- action: String(options.resolvedAction || requireFlag(flags, 'action', 'Missing --action')).trim(),
136
+ action,
135
137
  userDid: resolveEffectiveUserDid(flags, {
136
138
  runMode,
137
139
  hybridWalletMode: options.hybridWalletMode,
138
140
  preferDelegationIdentity: options.preferDelegationIdentity,
139
141
  }),
140
142
  params: managedParams,
141
- chainId: Number(flags.chainId || 8453),
143
+ chainId: resolveWalletExecuteChainId({
144
+ action,
145
+ chainId: flags.chainId,
146
+ params: managedParams,
147
+ }),
142
148
  executionStrategy: {
143
149
  runMode,
144
150
  mirrorOnly: false,
@@ -12,6 +12,7 @@ import {
12
12
  import { apiGet, apiPost } from '../../core/http.mjs';
13
13
  import { withActionTimeout } from '../../core/actionTimeouts.mjs';
14
14
  import { isReadOnlyResolvedAction } from '../../core/readOnlyActions.mjs';
15
+ import { resolveWalletExecuteChainId } from '../../core/walletExecuteChainId.mjs';
15
16
  import { isEmptyQueuedExecuteIntent, shouldFallbackManagedReadToExecuteIntent } from './managedReadExecuteRail.mjs';
16
17
  import { createRequire } from 'module';
17
18
 
@@ -637,7 +638,13 @@ async function executeHybridRun(ctx, flags, resolved, options) {
637
638
  }
638
639
 
639
640
  async function resolveManagedExecutionPreflight(ctx, flags, resolved, options = {}) {
640
- const chainId = Number(flags.chainId || 8453);
641
+ const action = String(resolved?.resolvedAction || flags.action || '').trim();
642
+ const params = getPreparedParams(flags);
643
+ const chainId = resolveWalletExecuteChainId({
644
+ action,
645
+ chainId: flags.chainId,
646
+ params,
647
+ });
641
648
  const runMode = String(options.runMode || 'agent_wallet').trim().toLowerCase();
642
649
  const agentApiKey = resolveAgentApiKey(flags, runMode);
643
650
  const userDid = resolveEffectiveUserDid(flags, {
@@ -657,10 +664,7 @@ async function resolveManagedExecutionPreflight(ctx, flags, resolved, options =
657
664
  signerMethod: 'managed_wallet_server',
658
665
  };
659
666
  }
660
- const tokenIn = resolveTokenInForFunding(
661
- getPreparedParams(flags),
662
- resolved?.resolvedAction || flags.action
663
- );
667
+ const tokenIn = resolveTokenInForFunding(params, action);
664
668
  const query = new URLSearchParams({
665
669
  userDid,
666
670
  chainId: String(chainId),
@@ -5,18 +5,8 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
5
5
  function getTradingProviderHint(providerId) {
6
6
  const provider = String(providerId || '').trim().toLowerCase();
7
7
  const manifestHint = getCachedProviderHintFromCapabilities(provider);
8
- if (manifestHint) return manifestHint;
9
- if (provider === 'trading') {
10
- return {
11
- provider,
12
- category: 'onchain_spot',
13
- canonicalWriteAction: 'swap',
14
- supportedChains: [1, 10, 130, 137, 8453, 84532, 42161, 4663],
15
- laneCompatibility:
16
- 'Kyber quote/build is live on Ethereum, Optimism, Unichain, Polygon, Base, and Arbitrum; sponsored Kyber execution is validated on Base only. Robinhood Chain (4663) uses Li.Fi Intents for spot swaps with user-pays gas. Gnosis FX uses the fx provider via CoW.',
17
- credentialUx: 'Use normal Thirdfy login/delegation; do not use this provider for Hyperliquid, Lighter, or Polymarket.',
18
- };
19
- }
8
+ const setupHints =
9
+ manifestHint?.setupHints && typeof manifestHint.setupHints === 'object' ? manifestHint.setupHints : {};
20
10
  if (provider === 'hyperliquid') {
21
11
  return {
22
12
  provider,
@@ -34,9 +24,11 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
34
24
  'get_hyperliquid_onboarding_plan',
35
25
  'get_hyperliquid_referral_status',
36
26
  'get_hyperliquid_builder_fee_status',
27
+ 'quote_hyperliquid_cctp_deposit',
37
28
  ],
38
29
  orderManagementActions: [
39
30
  'place_hyperliquid_perps_order',
31
+ 'place_hyperliquid_tp_sl',
40
32
  'cancel_hyperliquid_perps_order',
41
33
  'update_hyperliquid_leverage',
42
34
  'get_hyperliquid_open_orders',
@@ -47,13 +39,16 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
47
39
  'get_hyperliquid_onboarding_plan',
48
40
  'prepare_hyperliquid_onboarding',
49
41
  'complete_hyperliquid_onboarding',
42
+ 'quote_hyperliquid_cctp_deposit',
43
+ 'deposit_hyperliquid_cctp',
44
+ 'deposit_hyperliquid_bridge',
45
+ 'transfer_hyperliquid_spot_to_perps',
50
46
  'get_bridge_quote',
51
47
  'execute_bridge',
52
48
  'approve_hyperliquid_agent',
53
49
  'get_hyperliquid_builder_fee_status',
54
50
  'approve_hyperliquid_builder_fee',
55
51
  'set_hyperliquid_referrer',
56
- 'deposit_hyperliquid_bridge',
57
52
  'deposit_hyperliquid_staking',
58
53
  'claim_hyperliquid_testnet_faucet',
59
54
  ],
@@ -72,17 +67,14 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
72
67
  credentialType: 'hyperliquid_api_wallet',
73
68
  credentialUx:
74
69
  'Thirdfy manages Hyperliquid API-wallet setup for normal users. Delegated writes require encrypted privateKey-backed hyperliquid_api_wallet credentials; walletAddress-only records are rejected until Privy walletId-backed Hyperliquid signing ships.',
75
- recommendedFundingChainId: 42161,
76
70
  supportedFundingSourceChains: [
77
- { chainId: 42161, name: 'Arbitrum One', path: 'native USDC -> Bridge2' },
78
- { chainId: 8453, name: 'Base', path: 'Li.Fi -> Arbitrum native USDC -> Bridge2' },
79
- { chainId: 1, name: 'Ethereum', path: 'Li.Fi -> Arbitrum native USDC -> Bridge2' },
80
- { chainId: 137, name: 'Polygon', path: 'Li.Fi -> Arbitrum native USDC -> Bridge2' },
71
+ { chainId: 8453, name: 'Base' },
72
+ { chainId: 42161, name: 'Arbitrum One' },
73
+ { chainId: 137, name: 'Polygon' },
74
+ { chainId: 1, name: 'Ethereum' },
81
75
  ],
82
76
  setupBlockers: [
83
77
  'HYPERLIQUID_SOURCE_FUNDS_REQUIRED',
84
- 'HYPERLIQUID_ARBITRUM_USDC_REQUIRED',
85
- 'HYPERLIQUID_BRIDGE2_DEPOSIT_REQUIRED',
86
78
  'HYPERLIQUID_API_WALLET_APPROVAL_REQUIRED',
87
79
  'HYPERLIQUID_BUILDER_APPROVAL_REQUIRED',
88
80
  'HYPERLIQUID_POLICY_REQUIRED',
@@ -93,17 +85,32 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
93
85
  'HYPERLIQUID_BUILDER_WALLET_UNFUNDED',
94
86
  'HYPERLIQUID_API_WALLET_NOT_PROVIDED',
95
87
  ],
96
- sourceBridgeProvider: 'lifi',
97
88
  funding:
98
- 'Best path: Base/Ethereum/Polygon USDC -> Li.Fi bridge to native Arbitrum USDC -> Hyperliquid Bridge2. If the user already has native Circle USDC on Arbitrum One (42161), skip Li.Fi and call deposit_hyperliquid_bridge. Minimum 5 USDC; Bridge2 credits the sender/source wallet.',
89
+ 'Follow nextAction and nextActionParams from get_hyperliquid_funding_status. Do not invent a funding chain.',
99
90
  laneCompatibility:
100
- 'Use self/BYOW only for setup signatures or Arbitrum funding transactions. Perps order placement is an offchain venue write and should use thirdfy, hybrid, or agent_wallet. The default solo agent_wallet path uses the managed execution wallet as the Hyperliquid master address. If margin already sits on a distinct Hyperliquid main wallet, pass that as userAddress/mainWalletAddress and pass the approved execution/API wallet as apiWalletAddress.',
91
+ 'Use self/BYOW only for setup signatures or source-chain funding transactions. Perps order placement is an offchain venue write and should use thirdfy, hybrid, or agent_wallet. The default solo agent_wallet path uses the managed execution wallet as the Hyperliquid master address. If margin already sits on a distinct Hyperliquid main wallet, pass that as userAddress/mainWalletAddress and pass the approved execution/API wallet as apiWalletAddress.',
101
92
  setupExample:
102
- 'actions --provider hyperliquid -> get_hyperliquid_funding_status -> complete_hyperliquid_onboarding for runtime-owned setup, or get_hyperliquid_onboarding_plan/prepare_hyperliquid_onboarding for operator previews -> get_bridge_quote/execute_bridge if source is Base/Ethereum/Polygon -> deposit_hyperliquid_bridge on 42161 -> approve_hyperliquid_agent -> approve_hyperliquid_builder_fee only when get_hyperliquid_setup_status shows builder.enabled=true -> get_hyperliquid_setup_status before place_hyperliquid_perps_order',
93
+ 'actions --provider hyperliquid -> get_hyperliquid_funding_status -> complete_hyperliquid_onboarding for runtime-owned setup, or get_hyperliquid_onboarding_plan/prepare_hyperliquid_onboarding for operator previews -> follow nextAction with nextActionParams -> get_hyperliquid_setup_status before place_hyperliquid_perps_order',
103
94
  monetization:
104
95
  'Builder monetization is active only when the API operator configured a builder address and the builder treasury has Hyperliquid margin. When active, the main wallet signs approve_hyperliquid_builder_fee once and orders attach builder fees. When the treasury is unfunded, get_hyperliquid_setup_status can return ready=true with warning HYPERLIQUID_BUILDER_WALLET_UNFUNDED, get_hyperliquid_builder_fee_status returns monetizationEnabled=false with reason BUILDER_WALLET_UNFUNDED, and place_hyperliquid_perps_order does not require builder approval.',
105
96
  example:
106
97
  'thirdfy-agent actions --provider hyperliquid && thirdfy-agent preflight --action place_hyperliquid_perps_order --params \'{"coin":"ETH","isBuy":true,"size":0.01,"limitPx":3500,"orderType":"market"}\'',
98
+ ...(manifestHint || {}),
99
+ ...setupHints,
100
+ provider,
101
+ source: manifestHint ? 'cli_capabilities_manifest' : 'static_provider_hint',
102
+ };
103
+ }
104
+ if (manifestHint) return manifestHint;
105
+ if (provider === 'trading') {
106
+ return {
107
+ provider,
108
+ category: 'onchain_spot',
109
+ canonicalWriteAction: 'swap',
110
+ supportedChains: [1, 10, 130, 137, 8453, 84532, 42161, 4663],
111
+ laneCompatibility:
112
+ 'Kyber quote/build is live on Ethereum, Optimism, Unichain, Polygon, Base, and Arbitrum; sponsored Kyber execution is validated on Base only. Robinhood Chain (4663) uses Li.Fi Intents for spot swaps with user-pays gas. Gnosis FX uses the fx provider via CoW.',
113
+ credentialUx: 'Use normal Thirdfy login/delegation; do not use this provider for Hyperliquid, Lighter, or Polymarket.',
107
114
  };
108
115
  }
109
116
  if (provider === 'lighter') {
@@ -951,6 +958,7 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
951
958
  custodyMode: match.custodyMode || null,
952
959
  description: match.description || null,
953
960
  source: 'cli_capabilities_manifest',
961
+ ...(match.setupHints && typeof match.setupHints === 'object' ? { setupHints: match.setupHints } : {}),
954
962
  };
955
963
  }
956
964