@thirdfy/agent-cli 0.2.21 → 0.2.25
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 +33 -0
- package/README.md +11 -4
- package/package.json +3 -1
- package/src/commands/chat.mjs +1 -0
- package/src/runtime/execution/payloads.mjs +61 -6
- package/src/runtime/execution/runners.mjs +14 -3
- package/src/runtime/providerHints.mjs +20 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,39 @@ All notable changes to `@thirdfy/agent-cli` are documented here. The format is b
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.2.25] - 2026-07-11
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Solo `agent_wallet` still uses `did:wallet:<agentKey>`, but hybrid `agent_wallet` and `--signer-method managed_wallet_server` keep saved Privy delegation identity.
|
|
12
|
+
|
|
13
|
+
## [0.2.24] - 2026-07-11
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- `agent_wallet` execute-intent read-only fallback now passes `runMode: agent_wallet` into identity resolution so solo `did:wallet:<agentKey>` is used consistently.
|
|
18
|
+
|
|
19
|
+
## [0.2.23] - 2026-07-11
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Solo `agent_wallet` preflight now resolves `did:wallet:<agentKey>` from `--agent-key`, `THIRDFY_AGENT_KEY`, or `config.agent.agentKey` instead of falling back to subscriber Privy `userDid` (fixes `SUBSCRIPTION_NOT_FOUND` on Robinhood and other direct agent lanes).
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- `npm run validate:robinhood-agent-wallet-preflight` for live API solo agent_wallet preflight on chain 4663.
|
|
28
|
+
|
|
29
|
+
## [0.2.22] - 2026-07-10
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Robinhood Chain (4663) provider hints for trading, bridge, yield-xyz, and market-data; `robinhood-mainnet` chat alias; live capabilities validation for 4663.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Capabilities-derived hints no longer set a write action for read-only `market-data`.
|
|
38
|
+
- Live API validation also asserts `yield-xyz` includes chain 4663.
|
|
39
|
+
|
|
7
40
|
## [0.2.21] - 2026-07-05
|
|
8
41
|
|
|
9
42
|
### Added
|
package/README.md
CHANGED
|
@@ -40,11 +40,18 @@ Run without global install:
|
|
|
40
40
|
npx @thirdfy/agent-cli --help
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
## What's new in v0.2.
|
|
43
|
+
## What's new in v0.2.25
|
|
44
44
|
|
|
45
|
-
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
- Hybrid and `managed_wallet_server` agent_wallet paths keep Privy delegation identity; solo Robinhood lane still uses `did:wallet:<agentKey>`.
|
|
46
|
+
|
|
47
|
+
## What's new in v0.2.24
|
|
48
|
+
|
|
49
|
+
- `agent_wallet` read-only execute-intent fallback keeps solo `did:wallet:<agentKey>` identity (matches preflight and primary execute path).
|
|
50
|
+
|
|
51
|
+
## What's new in v0.2.23
|
|
52
|
+
|
|
53
|
+
- Solo `agent_wallet` preflight uses `did:wallet:<agentKey>` so Robinhood and direct agent lanes skip subscriber delegation (`SUBSCRIPTION_NOT_FOUND` fix).
|
|
54
|
+
- `npm run validate:robinhood-agent-wallet-preflight` for live chain 4663 execution-wallet checks.
|
|
48
55
|
|
|
49
56
|
Older versions: see [CHANGELOG.md](./CHANGELOG.md) and [GitHub Releases](https://github.com/thirdfy/agent-cli/releases).
|
|
50
57
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thirdfy/agent-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.25",
|
|
4
4
|
"description": "Thirdfy Agent CLI for onboarding, governance preflight, execute-intent, and status polling.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -47,6 +47,8 @@
|
|
|
47
47
|
"smoke:cli": "node ./bin/thirdfy-agent.mjs --help && node ./bin/thirdfy-agent.mjs -V && node ./bin/thirdfy-agent.mjs --version --json",
|
|
48
48
|
"validate:release-preflight": "npm run lint && npm run validate:public-docs && npm run validate:cli-contract-schemas && npm run validate:provider-parity && npm run validate:cli-manifest-handlers && npm run validate:runtime-boundaries && npm run test && npm run validate:npm-pack && npm run smoke:cli",
|
|
49
49
|
"validate:live-api-capabilities": "node ./scripts/validate-live-api-capabilities.mjs",
|
|
50
|
+
"validate:robinhood-agent-wallet-preflight": "node ./scripts/validate-robinhood-agent-wallet-preflight.mjs",
|
|
51
|
+
"validate:robinhood-agent-wallet-preflight": "node ./scripts/validate-robinhood-agent-wallet-preflight.mjs",
|
|
50
52
|
"prepublishOnly": "npm run validate:release-preflight"
|
|
51
53
|
},
|
|
52
54
|
"keywords": [
|
package/src/commands/chat.mjs
CHANGED
|
@@ -16,13 +16,57 @@ function buildBuildTxPayload(flags, resolvedAction) {
|
|
|
16
16
|
return payload;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
function
|
|
19
|
+
function resolveAgentKey(flags) {
|
|
20
|
+
const explicit = String(flags.agentKey || '').trim();
|
|
21
|
+
if (explicit) return explicit.toLowerCase();
|
|
22
|
+
const envKey = String(process.env.THIRDFY_AGENT_KEY || process.env.AGENT_KEY || '').trim();
|
|
23
|
+
if (envKey) return envKey.toLowerCase();
|
|
24
|
+
const config = loadProfileConfig();
|
|
25
|
+
const configKey = String(config?.agent?.agentKey || '').trim();
|
|
26
|
+
if (configKey) return configKey.toLowerCase();
|
|
27
|
+
return '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function buildSoloAgentWalletUserDid(agentKey) {
|
|
31
|
+
const normalized = String(agentKey || '').trim().toLowerCase();
|
|
32
|
+
if (!normalized) return '';
|
|
33
|
+
return `did:wallet:${normalized}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function isWalletScopedUserDid(value) {
|
|
37
|
+
return String(value || '').trim().toLowerCase().startsWith('did:wallet:');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function preferDelegationAgentWalletIdentity(flags, options = {}) {
|
|
41
|
+
if (options.preferDelegationIdentity === true) return true;
|
|
42
|
+
if (String(flags.runMode || '').trim().toLowerCase() === 'hybrid') return true;
|
|
43
|
+
if (options.hybridWalletMode) return true;
|
|
44
|
+
const signerMethod = String(flags.signerMethod || '').trim().toLowerCase();
|
|
45
|
+
if (signerMethod === 'managed_wallet_server') return true;
|
|
46
|
+
const scope = String(flags.executionScope || '').trim();
|
|
47
|
+
if (scope && scope !== 'solo_owner_mirror') return true;
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function resolveEffectiveUserDid(flags, options = {}) {
|
|
20
52
|
const explicit = String(flags.userDid || '').trim();
|
|
21
53
|
if (explicit) return explicit;
|
|
54
|
+
const runMode = String(options.runMode || flags.runMode || '').trim().toLowerCase();
|
|
22
55
|
const envUserDid = String(process.env.THIRDFY_USER_DID || '').trim();
|
|
23
|
-
if (envUserDid) return envUserDid;
|
|
24
56
|
const config = loadProfileConfig();
|
|
25
|
-
|
|
57
|
+
const configUserDid = String(config?.wallets?.userDid || config?.identity?.userDid || '').trim();
|
|
58
|
+
|
|
59
|
+
// Solo agent_wallet uses did:wallet:<agentKey>. Hybrid and managed_wallet_server keep Privy delegation.
|
|
60
|
+
if (runMode === 'agent_wallet' && !preferDelegationAgentWalletIdentity(flags, options)) {
|
|
61
|
+
const soloDid = buildSoloAgentWalletUserDid(resolveAgentKey(flags));
|
|
62
|
+
if (soloDid) return soloDid;
|
|
63
|
+
if (isWalletScopedUserDid(envUserDid)) return envUserDid;
|
|
64
|
+
if (isWalletScopedUserDid(configUserDid)) return configUserDid;
|
|
65
|
+
return '';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (envUserDid) return envUserDid;
|
|
69
|
+
return configUserDid;
|
|
26
70
|
}
|
|
27
71
|
|
|
28
72
|
function buildManagedExecutePayload(flags, options) {
|
|
@@ -55,7 +99,11 @@ function buildManagedExecutePayload(flags, options) {
|
|
|
55
99
|
const payload = {
|
|
56
100
|
agentApiKey: resolveAgentApiKey(flags, runMode),
|
|
57
101
|
action: String(options.resolvedAction || requireFlag(flags, 'action', 'Missing --action')).trim(),
|
|
58
|
-
userDid: resolveEffectiveUserDid(flags
|
|
102
|
+
userDid: resolveEffectiveUserDid(flags, {
|
|
103
|
+
runMode,
|
|
104
|
+
hybridWalletMode: options.hybridWalletMode,
|
|
105
|
+
preferDelegationIdentity: options.preferDelegationIdentity,
|
|
106
|
+
}),
|
|
59
107
|
params: managedParams,
|
|
60
108
|
chainId: Number(flags.chainId || 8453),
|
|
61
109
|
executionStrategy: {
|
|
@@ -66,7 +114,7 @@ function buildManagedExecutePayload(flags, options) {
|
|
|
66
114
|
if (!payload.userDid) {
|
|
67
115
|
throw createCliError(
|
|
68
116
|
'MISSING_USER_DID',
|
|
69
|
-
'Managed wallet execution requires --user-did, THIRDFY_USER_DID, or a saved userDid from `thirdfy-agent login email`.'
|
|
117
|
+
'Managed wallet execution requires --user-did, --agent-key (solo did:wallet identity), THIRDFY_USER_DID, or a saved userDid from `thirdfy-agent login email`.'
|
|
70
118
|
);
|
|
71
119
|
}
|
|
72
120
|
if (flags.estimatedAmountUsd) payload.estimatedAmountUsd = Number(flags.estimatedAmountUsd);
|
|
@@ -96,7 +144,12 @@ function buildIntentPayload(flags, options) {
|
|
|
96
144
|
if (flags.catalog) payload.catalog = String(flags.catalog).trim();
|
|
97
145
|
if (flags.chainId) payload.chainId = Number(flags.chainId);
|
|
98
146
|
if (flags.estimatedAmountUsd) payload.estimatedAmountUsd = Number(flags.estimatedAmountUsd);
|
|
99
|
-
const
|
|
147
|
+
const intentRunMode = String(options.runMode || flags.runMode || '').trim().toLowerCase();
|
|
148
|
+
const userDid = resolveEffectiveUserDid(flags, {
|
|
149
|
+
runMode: intentRunMode,
|
|
150
|
+
hybridWalletMode: options.hybridWalletMode,
|
|
151
|
+
preferDelegationIdentity: options.preferDelegationIdentity,
|
|
152
|
+
});
|
|
100
153
|
if (flags.userDid || (options.validationOnly && (runMode === 'agent_wallet' || (runMode === 'hybrid' && options.mirrorOnly)))) {
|
|
101
154
|
if (userDid) payload.userDid = userDid;
|
|
102
155
|
}
|
|
@@ -139,6 +192,8 @@ function resolveAgentApiKey(flags, runMode) {
|
|
|
139
192
|
|
|
140
193
|
return {
|
|
141
194
|
buildBuildTxPayload,
|
|
195
|
+
resolveAgentKey,
|
|
196
|
+
buildSoloAgentWalletUserDid,
|
|
142
197
|
resolveEffectiveUserDid,
|
|
143
198
|
buildManagedExecutePayload,
|
|
144
199
|
resolveTokenInForFunding,
|
|
@@ -338,7 +338,11 @@ async function executeManagedWalletRun(ctx, flags, resolved, options) {
|
|
|
338
338
|
const actionCtx = withActionTimeout(ctx, resolved.resolvedAction);
|
|
339
339
|
const response = await apiPost(actionCtx, '/api/v1/agent/execute', payload);
|
|
340
340
|
if (shouldFallbackAgentWalletToExecuteIntent(resolved, response)) {
|
|
341
|
-
const userDid = resolveEffectiveUserDid(flags
|
|
341
|
+
const userDid = resolveEffectiveUserDid(flags, {
|
|
342
|
+
runMode: 'agent_wallet',
|
|
343
|
+
hybridWalletMode: options.hybridWalletMode,
|
|
344
|
+
preferDelegationIdentity: options.preferDelegationIdentity,
|
|
345
|
+
});
|
|
342
346
|
const chainId = Number(flags.chainId || 8453);
|
|
343
347
|
const intentResult = await executeThirdfyRun(
|
|
344
348
|
ctx,
|
|
@@ -493,13 +497,20 @@ async function resolveManagedExecutionPreflight(ctx, flags, resolved, options =
|
|
|
493
497
|
const chainId = Number(flags.chainId || 8453);
|
|
494
498
|
const runMode = String(options.runMode || 'agent_wallet').trim().toLowerCase();
|
|
495
499
|
const agentApiKey = resolveAgentApiKey(flags, runMode);
|
|
496
|
-
const userDid = resolveEffectiveUserDid(flags
|
|
500
|
+
const userDid = resolveEffectiveUserDid(flags, {
|
|
501
|
+
runMode,
|
|
502
|
+
hybridWalletMode: options.hybridWalletMode,
|
|
503
|
+
preferDelegationIdentity: options.preferDelegationIdentity,
|
|
504
|
+
});
|
|
497
505
|
if (!userDid) {
|
|
498
506
|
return {
|
|
499
507
|
success: false,
|
|
500
508
|
blockedReason: 'MISSING_USER_DID',
|
|
501
509
|
blockedStage: 'routing',
|
|
502
|
-
error:
|
|
510
|
+
error:
|
|
511
|
+
runMode === 'agent_wallet'
|
|
512
|
+
? 'Solo agent_wallet requires --agent-key, THIRDFY_AGENT_KEY, config.agent.agentKey, or --user-did did:wallet:<agentKey>. Subscriber Privy DIDs require delegation; use did:wallet for direct agent execution.'
|
|
513
|
+
: 'Managed wallet execution requires --user-did, THIRDFY_USER_DID, or a saved userDid from `thirdfy-agent login email`.',
|
|
503
514
|
signerMethod: 'managed_wallet_server',
|
|
504
515
|
};
|
|
505
516
|
}
|
|
@@ -11,9 +11,9 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
|
|
|
11
11
|
provider,
|
|
12
12
|
category: 'onchain_spot',
|
|
13
13
|
canonicalWriteAction: 'swap',
|
|
14
|
-
supportedChains: [1, 10, 130, 137, 8453, 84532, 42161],
|
|
14
|
+
supportedChains: [1, 10, 130, 137, 8453, 84532, 42161, 4663],
|
|
15
15
|
laneCompatibility:
|
|
16
|
-
'Kyber quote/build is live on Ethereum, Optimism, Unichain, Polygon, Base, and Arbitrum; sponsored Kyber execution is validated on Base only. Gnosis FX uses the fx provider via CoW.',
|
|
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
17
|
credentialUx: 'Use normal Thirdfy login/delegation; do not use this provider for Hyperliquid, Lighter, or Polymarket.',
|
|
18
18
|
};
|
|
19
19
|
}
|
|
@@ -329,7 +329,7 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
|
|
|
329
329
|
canonicalWriteAction: 'execute_bridge',
|
|
330
330
|
readActions: ['get_bridge_quote', 'get_supported_bridge_chains', 'check_bridge_status'],
|
|
331
331
|
orderManagementActions: ['execute_bridge'],
|
|
332
|
-
supportedChains: [1, 8453, 42161, 10, 137, 56, 43114, 250, 100, 1284, 1285, 25, 288, 1088, 42220, 122, 324, 59144, 534352, 5000, 81457, 169],
|
|
332
|
+
supportedChains: [1, 8453, 42161, 10, 137, 56, 43114, 250, 100, 1284, 1285, 25, 288, 1088, 42220, 122, 324, 59144, 534352, 5000, 81457, 169, 4663],
|
|
333
333
|
laneCompatibility: 'Li.Fi bridge supports mainnet value movement only; testnets are not auto-mapped to mainnet.',
|
|
334
334
|
};
|
|
335
335
|
}
|
|
@@ -455,6 +455,22 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
|
|
|
455
455
|
'Yield.xyz writes are transaction-prep first. Thirdfy calls Yield.xyz directly and validates returned unsigned transactions with @yieldxyz/shield before signing or returning prepared calls.',
|
|
456
456
|
example:
|
|
457
457
|
'thirdfy-agent actions --provider yield-xyz && thirdfy-agent preflight --action deposit_earn_position --params \'{"providerId":"yield-xyz","opportunityId":"ethereum-eth-lido-staking","tokenAddress":"0x...","amount":"0.01","chainId":1}\'',
|
|
458
|
+
supportedChains: [1, 10, 100, 130, 137, 42220, 8453, 42161, 4663],
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
if (provider === 'market-data') {
|
|
462
|
+
return {
|
|
463
|
+
provider,
|
|
464
|
+
category: 'market_data',
|
|
465
|
+
canonicalReadAction: 'get_trending_tokens',
|
|
466
|
+
readActions: [
|
|
467
|
+
'get_trending_tokens',
|
|
468
|
+
'get_new_token_launches',
|
|
469
|
+
'get_token_market_data',
|
|
470
|
+
'get_chain_market_overview',
|
|
471
|
+
],
|
|
472
|
+
supportedChains: [8453, 84532, 4663],
|
|
473
|
+
laneCompatibility: 'Read-only market data via API-owned actions. Robinhood Chain uses CoinGecko Onchain network id robinhood.',
|
|
458
474
|
};
|
|
459
475
|
}
|
|
460
476
|
return null;
|
|
@@ -488,6 +504,7 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
|
|
|
488
504
|
curve: 'get_curve_pools',
|
|
489
505
|
'vaults-fyi': 'get-vaults-fyi-vaults',
|
|
490
506
|
'yield-xyz': 'get_yield_xyz_opportunities',
|
|
507
|
+
'market-data': 'get_trending_tokens',
|
|
491
508
|
prediction: 'get_prediction_markets',
|
|
492
509
|
};
|
|
493
510
|
return {
|