@thirdfy/agent-cli 0.2.43 → 0.2.46

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,24 @@ All notable changes to `@thirdfy/agent-cli` are documented here. The format is b
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.2.46] - 2026-08-08
8
+
9
+ ### Changed
10
+
11
+ - Yield.xyz provider hints: require discovery (`get_yield_xyz_opportunities`) before deposit; document that Thirdfy prepareDeposit calls `GET /v1/yields/{yieldId}` before enter/exit. Example uses Base USDC + canonical yieldId. Pairs with Thirdfy API 3.13.55 + thirdfy-mcp 0.0.94.
12
+
13
+ ## [0.2.45] - 2026-08-06
14
+
15
+ ### Added
16
+
17
+ - Polymarket provider hints: official Bridge deposit/withdraw actions; Li.Fi `get_bridge_quote` documented as legacy fallback for PM collateral only.
18
+ - `console-mandate` accepts `--chain-id` / `--network` (aligned with MCP `consoleMandateChains`: Gnosis 100, Robinhood 4663, Base 8453). Multi-chain Automations need one mandate per write chain.
19
+ - Chat / mandate network map includes Gnosis, Unichain, Polygon, Arbitrum, Ethereum, Optimism, DogeOS testnet.
20
+
21
+ ### Fixed
22
+
23
+ - Read-only classifier parity: `create_polymarket_bridge_deposit` and `create_polymarket_bridge_withdraw` route as setup reads (aligned with Thirdfy API `actionContractManifest`).
24
+
7
25
  ## [0.2.43] - 2026-07-31
8
26
 
9
27
  ### Added
package/README.md CHANGED
@@ -40,12 +40,10 @@ Run without global install:
40
40
  npx @thirdfy/agent-cli --help
41
41
  ```
42
42
 
43
- ## What's new in v0.2.43
43
+ ## What's new in v0.2.46
44
44
 
45
- - Aave earn provider routing (`get_aave_markets`, supply/withdraw, lending beta actions).
46
- - Polymarket `status`/`setup` return live execute payloads; `prepare_polymarket_onboarding` is read-only.
47
-
48
- See [CHANGELOG.md](./CHANGELOG.md) for older versions.
45
+ - Yield.xyz: discover opportunities first, then deposit with the canonical yieldId. Thirdfy prepare calls yields_get before enter/exit.
46
+ - See [CHANGELOG.md](./CHANGELOG.md) for older versions.
49
47
 
50
48
 
51
49
  ## Quick start
@@ -325,7 +323,8 @@ Provider and venue guides are kept outside `README` so this page stays stable as
325
323
  - Discovery: `catalogs list`, `actions` (optional `--provider`, `--chain-id`; see [`docs/command-reference.md`](./docs/command-reference.md) for trading vs earn vs prediction providers and case-insensitive matching)
326
324
  - Execution: `preflight`, `run`, `intent-status`, `jeff preflight`, `jeff trade`, `jeff status`
327
325
  - Polymarket: `polymarket status`, `polymarket setup`, `polymarket dry-run`
328
- - Hummingbot: `hummingbot status`, `hummingbot connectors`, `hummingbot executor-schema`, `hummingbot executor-create`
326
+ - Hummingbot: `hummingbot status`, `connectors`, `executor-schema`, `executor-create`, `executor-stop`, `gateway-networks`, `gateway-connectors`
327
+ - Condor Pattern A: `condor policy-status`, `condor preflight`
329
328
  - Managed signer execution: `wallet execute`, `wallet sign`, `wallet submit`, `agent run`
330
329
  - Profiles: `profile init`, `profile use`, `profile show`, `whoami`
331
330
  - Onboarding: `login email`, `help onboarding`, `doctor auth`, `wallet list`, `bootstrap begin`, `bootstrap complete`, `onboarding begin`, `onboarding complete`, `agent auth challenge`, `agent auth verify`, `agent register`, `agent key rotate`, `agent key revoke`, `developer bootstrap`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdfy/agent-cli",
3
- "version": "0.2.43",
3
+ "version": "0.2.46",
4
4
  "description": "Thirdfy Agent CLI for onboarding, governance preflight, execute-intent, and status polling.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli/help.mjs CHANGED
@@ -42,6 +42,11 @@ Core commands:
42
42
  thirdfy-agent hummingbot connectors [--org-id <id>] [--json]
43
43
  thirdfy-agent hummingbot executor-schema [--org-id <id>] [--executor-type position_executor] [--json]
44
44
  thirdfy-agent hummingbot executor-create --agent-api-key <key> --user-did <did> [--org-id <id>] [--connector <name>] [--pair <pair>] [--params <json>] [--json]
45
+ thirdfy-agent hummingbot executor-stop --agent-api-key <key> --user-did <did> --executor-id <id> [--org-id <id>] [--json]
46
+ thirdfy-agent hummingbot gateway-networks --agent-api-key <key> --user-did <did> [--org-id <id>] [--json]
47
+ thirdfy-agent hummingbot gateway-connectors --agent-api-key <key> --user-did <did> [--org-id <id>] [--json]
48
+ thirdfy-agent condor policy-status --agent-api-key <key> --user-did <did> [--org-id <id>] [--runtime-id <id>] [--json]
49
+ thirdfy-agent condor preflight --agent-api-key <key> --user-did <did> --estimated-amount-usd <usd> --idempotency-key <key> [--org-id <id>] [--runtime-id <id>] [--connector <name>] [--pair <pair>] [--json]
45
50
  thirdfy-agent wallet sign --agent-api-key <key> --action <id> --params <json> [--chain-id <id>] [--json]
46
51
  thirdfy-agent wallet submit --signed-tx-hex <hex> [--chain-id <id>] [--rpc-url <url>] [--json]
47
52
  thirdfy-agent agent run --agent-api-key <key> --action <id> --params <json> [--signer-method managed_wallet_server|byow|fanout_intent] [--strategy-intent single_wallet|fanout] [--run-mode <mode>] [--user-did <did>] [--json]
@@ -148,6 +148,41 @@ export const CLI_MANIFEST = [
148
148
  options: ['auth', 'execution', 'hummingbot'],
149
149
  description: 'Governed Hummingbot executor create via Thirdfy proxy',
150
150
  },
151
+ {
152
+ path: ['hummingbot', 'executor-stop'],
153
+ handler: 'commandHummingbotExecutorStop',
154
+ tier: 'online',
155
+ options: ['auth', 'execution', 'hummingbot'],
156
+ description: 'Governed Hummingbot executor stop via Thirdfy proxy',
157
+ },
158
+ {
159
+ path: ['hummingbot', 'gateway-networks'],
160
+ handler: 'commandHummingbotGatewayNetworks',
161
+ tier: 'online',
162
+ options: ['auth', 'execution', 'hummingbot'],
163
+ description: 'Gateway network discovery via catalog read get_hummingbot_gateway_networks',
164
+ },
165
+ {
166
+ path: ['hummingbot', 'gateway-connectors'],
167
+ handler: 'commandHummingbotGatewayConnectors',
168
+ tier: 'online',
169
+ options: ['auth', 'execution', 'hummingbot'],
170
+ description: 'Gateway connector discovery via catalog read get_hummingbot_gateway_connectors',
171
+ },
172
+ {
173
+ path: ['condor', 'policy-status'],
174
+ handler: 'commandCondorPolicyStatus',
175
+ tier: 'online',
176
+ options: ['auth', 'execution', 'condor'],
177
+ description: 'Condor Pattern A policy status via catalog read get_condor_policy_status',
178
+ },
179
+ {
180
+ path: ['condor', 'preflight'],
181
+ handler: 'commandCondorPreflight',
182
+ tier: 'online',
183
+ options: ['auth', 'execution', 'condor'],
184
+ description: 'Condor Pattern A preflight reservation via governance/preflight (condor.executor.create)',
185
+ },
151
186
  // online
152
187
  {
153
188
  path: ['agent', 'run'],
@@ -388,28 +423,28 @@ export const CLI_MANIFEST = [
388
423
  path: ['console-mandate', 'status'],
389
424
  handler: 'commandConsoleMandateStatus',
390
425
  tier: 'online',
391
- options: ['auth', 'delegation'],
426
+ options: ['auth', 'delegation', 'chains'],
392
427
  description: 'Console delegated execution status',
393
428
  },
394
429
  {
395
430
  path: ['console-mandate', 'draft'],
396
431
  handler: 'commandConsoleMandateDraft',
397
432
  tier: 'online',
398
- options: ['auth', 'delegation'],
433
+ options: ['auth', 'delegation', 'chains'],
399
434
  description: 'Create Console mandate draft',
400
435
  },
401
436
  {
402
437
  path: ['console-mandate', 'activate'],
403
438
  handler: 'commandConsoleMandateActivate',
404
439
  tier: 'online',
405
- options: ['auth', 'delegation'],
440
+ options: ['auth', 'delegation', 'chains'],
406
441
  description: 'Activate signed Console mandate',
407
442
  },
408
443
  {
409
444
  path: ['console-mandate', 'revoke'],
410
445
  handler: 'commandConsoleMandateRevoke',
411
446
  tier: 'online',
412
- options: ['auth', 'delegation'],
447
+ options: ['auth', 'delegation', 'chains'],
413
448
  description: 'Revoke Console mandate',
414
449
  },
415
450
  {
@@ -0,0 +1,7 @@
1
+ export function attachCondorOptions(cmd) {
2
+ return cmd
3
+ .option('--org-id <id>', 'Condor org id (default: HUMMINGBOT_ORG_ID or default)')
4
+ .option('--runtime-id <id>', 'EarnClaw runtime id for policy scoping')
5
+ .option('--connector <name>', 'CEX connector for preflight params')
6
+ .option('--pair <pair>', 'Trading pair for preflight params');
7
+ }
@@ -6,6 +6,8 @@ export function attachDelegationOptions(cmd) {
6
6
  .option('--max-usd-per-day <usd>', 'max USD per day')
7
7
  .option('--period-duration <sec>', 'period duration seconds')
8
8
  .option('--expiry-seconds <sec>', 'expiry seconds')
9
+ // `--chain-id` comes from the `chains` option bundle (avoid duplicate on init-custodial).
10
+ .option('--network <id>', 'network id (e.g. gnosis-mainnet, robinhood-mainnet)')
9
11
  .option('--delegation-manager <addr>', 'delegation manager address')
10
12
  .option('--delegation <json>', 'delegation JSON')
11
13
  .option('--permission <json>', 'permission JSON')
@@ -3,6 +3,7 @@ export function attachHummingbotOptions(cmd) {
3
3
  .option('--org-id <id>', 'Hummingbot org id (default: HUMMINGBOT_ORG_ID or default)')
4
4
  .option('--runtime-id <id>', 'EarnClaw runtime id for health summary scoping')
5
5
  .option('--executor-type <type>', 'Hummingbot executor type')
6
+ .option('--executor-id <id>', 'Hummingbot executor id for stop')
6
7
  .option('--connector <name>', 'Hummingbot connector name')
7
8
  .option('--pair <pair>', 'Hummingbot trading pair');
8
9
  }
@@ -9,6 +9,7 @@ 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
+ import { attachCondorOptions } from './condor.mjs';
12
13
  import { attachAgentRegisterOptions } from './agent.mjs';
13
14
  import { attachChainOptions } from './chains.mjs';
14
15
  import { attachCreditsOptions } from './credits.mjs';
@@ -28,6 +29,7 @@ const BUNDLES = {
28
29
  analytics: attachAnalyticsOptions,
29
30
  polymarket: attachPolymarketOptions,
30
31
  hummingbot: attachHummingbotOptions,
32
+ condor: attachCondorOptions,
31
33
  agent: attachAgentRegisterOptions,
32
34
  chains: attachChainOptions,
33
35
  credits: attachCreditsOptions,
@@ -5,7 +5,14 @@ import { apiGet, safeJsonParse } from '../core/http.mjs';
5
5
  const NETWORK_CHAIN_IDS = {
6
6
  'base-mainnet': 8453,
7
7
  'base-sepolia': 84532,
8
+ 'ethereum-mainnet': 1,
9
+ 'optimism-mainnet': 10,
10
+ 'gnosis-mainnet': 100,
11
+ 'unichain-mainnet': 130,
12
+ 'polygon-mainnet': 137,
13
+ 'arbitrum-mainnet': 42161,
8
14
  'robinhood-mainnet': 4663,
15
+ 'dogeos-testnet': 6281971,
9
16
  };
10
17
 
11
18
  const DEFAULT_CHAT_CHAIN_ID = 8453;
@@ -0,0 +1,130 @@
1
+ import { apiPost } from '../core/http.mjs';
2
+ import { parseJsonFlag } from '../core/args.mjs';
3
+ import { negotiateCapabilities } from '../core/http.mjs';
4
+ import { resolveConfigAgentKey } from './polymarket.mjs';
5
+
6
+ function agentApiKeyFromFlags(flags, ctx) {
7
+ return String(flags.agentApiKey || flags.agent_api_key || ctx?.agentApiKey || '').trim();
8
+ }
9
+
10
+ function userDidFromFlags(flags) {
11
+ return String(flags.userDid || flags.user_did || '').trim();
12
+ }
13
+
14
+ function orgIdFromFlags(flags) {
15
+ return String(flags.orgId || flags.org_id || process.env.HUMMINGBOT_ORG_ID || 'default').trim();
16
+ }
17
+
18
+ function runtimeIdFromFlags(flags) {
19
+ return String(flags.runtimeId || flags.runtime_id || '').trim();
20
+ }
21
+
22
+ function failMissingIdentity(printEnvelope, ctx, message) {
23
+ printEnvelope({
24
+ success: false,
25
+ code: 'MISSING_AUTH',
26
+ message,
27
+ data: {},
28
+ meta: { apiBase: ctx.apiBase },
29
+ });
30
+ process.exit(1);
31
+ }
32
+
33
+ export function createCondorCommands({ commandRun, printEnvelope }) {
34
+ async function commandCondorPolicyStatus(ctx, flags) {
35
+ const agentApiKey = agentApiKeyFromFlags(flags, ctx);
36
+ const userDid = userDidFromFlags(flags);
37
+ if (!agentApiKey || !userDid) {
38
+ failMissingIdentity(
39
+ printEnvelope,
40
+ ctx,
41
+ 'Provide --agent-api-key and --user-did for Condor policy status'
42
+ );
43
+ }
44
+ const capabilities = await negotiateCapabilities(ctx);
45
+ if (!flags.runMode) flags.runMode = 'thirdfy';
46
+ flags.provider = 'condor';
47
+ flags.action = 'get_condor_policy_status';
48
+ const params = parseJsonFlag(flags, 'params') || {};
49
+ flags.params = JSON.stringify({
50
+ orgId: orgIdFromFlags(flags),
51
+ ...(runtimeIdFromFlags(flags) ? { runtimeId: runtimeIdFromFlags(flags) } : {}),
52
+ ...params,
53
+ });
54
+ await commandRun(ctx, flags, capabilities);
55
+ }
56
+
57
+ async function commandCondorPreflight(ctx, flags) {
58
+ const agentApiKey = agentApiKeyFromFlags(flags, ctx);
59
+ const userDid = userDidFromFlags(flags);
60
+ const idempotencyKey = String(flags.idempotencyKey || flags.idempotency_key || '').trim();
61
+ const estimatedAmountUsd = Number(flags.estimatedAmountUsd || flags.estimated_amount_usd || 0);
62
+ if (!agentApiKey || !userDid) {
63
+ failMissingIdentity(
64
+ printEnvelope,
65
+ ctx,
66
+ 'Provide --agent-api-key and --user-did for Condor preflight'
67
+ );
68
+ }
69
+ if (!idempotencyKey) {
70
+ printEnvelope({
71
+ success: false,
72
+ code: 'MISSING_IDEMPOTENCY',
73
+ message: 'Provide --idempotency-key for Condor Pattern A preflight',
74
+ data: {},
75
+ meta: { apiBase: ctx.apiBase },
76
+ });
77
+ process.exit(1);
78
+ }
79
+ if (!Number.isFinite(estimatedAmountUsd) || estimatedAmountUsd <= 0) {
80
+ printEnvelope({
81
+ success: false,
82
+ code: 'MISSING_NOTIONAL',
83
+ message: 'Provide --estimated-amount-usd greater than zero for Condor preflight',
84
+ data: {},
85
+ meta: { apiBase: ctx.apiBase },
86
+ });
87
+ process.exit(1);
88
+ }
89
+ const params = parseJsonFlag(flags, 'params') || {};
90
+ const orgId = orgIdFromFlags(flags);
91
+ const runtimeId = runtimeIdFromFlags(flags);
92
+ const agentKey = String(flags.agentKey || flags.agent_key || resolveConfigAgentKey(flags) || '').trim();
93
+ const body = {
94
+ agentApiKey,
95
+ action: 'condor.executor.create',
96
+ userDid,
97
+ estimatedAmountUsd,
98
+ idempotencyKey,
99
+ executionLane: 'validation_only',
100
+ params: {
101
+ orgId,
102
+ ...(runtimeId ? { runtimeId } : {}),
103
+ ...(agentKey ? { agentKey } : {}),
104
+ connector: flags.connector || params.connector,
105
+ tradingPair: flags.pair || flags.tradingPair || params.tradingPair || params.trading_pair,
106
+ notionalUsd: estimatedAmountUsd,
107
+ source: 'condor_pattern_a',
108
+ ...params,
109
+ },
110
+ };
111
+ const data = await apiPost(ctx, '/api/v1/agent/governance/preflight', body, {
112
+ 'x-agent-api-key': agentApiKey,
113
+ });
114
+ printEnvelope({
115
+ success: Boolean(data?.success ?? true),
116
+ data,
117
+ meta: {
118
+ apiBase: ctx.apiBase,
119
+ orgId,
120
+ runtimeId: runtimeId || null,
121
+ action: 'condor.executor.create',
122
+ },
123
+ });
124
+ }
125
+
126
+ return {
127
+ commandCondorPolicyStatus,
128
+ commandCondorPreflight,
129
+ };
130
+ }
@@ -1,6 +1,38 @@
1
1
  import { requireFlag } from '../core/args.mjs';
2
2
  import { apiGet, apiPost } from '../core/http.mjs';
3
3
 
4
+ /** Aligned with chat.mjs NETWORK_CHAIN_IDS and thirdfy-mcp consoleMandateChains. */
5
+ const CONSOLE_MANDATE_NETWORK_CHAIN_IDS = {
6
+ 'base-mainnet': 8453,
7
+ 'base-sepolia': 84532,
8
+ 'ethereum-mainnet': 1,
9
+ 'optimism-mainnet': 10,
10
+ 'gnosis-mainnet': 100,
11
+ 'unichain-mainnet': 130,
12
+ 'polygon-mainnet': 137,
13
+ 'arbitrum-mainnet': 42161,
14
+ 'robinhood-mainnet': 4663,
15
+ 'dogeos-testnet': 6281971,
16
+ };
17
+
18
+ function resolveConsoleMandateChainId(flags) {
19
+ if (flags.chainId) {
20
+ const parsed = Number(flags.chainId);
21
+ if (Number.isFinite(parsed) && parsed > 0) return parsed;
22
+ throw new Error(`Invalid --chain-id "${flags.chainId}". Must be a positive number.`);
23
+ }
24
+ const networkRaw = String(flags.network || '').trim();
25
+ const network = networkRaw.toLowerCase();
26
+ if (network) {
27
+ const chainId = CONSOLE_MANDATE_NETWORK_CHAIN_IDS[network];
28
+ if (chainId !== undefined) return chainId;
29
+ throw new Error(
30
+ `Unknown --network "${networkRaw}". Supported: ${Object.keys(CONSOLE_MANDATE_NETWORK_CHAIN_IDS).join(', ')}`,
31
+ );
32
+ }
33
+ return 8453;
34
+ }
35
+
4
36
  export function createConsoleMandateCommands(deps) {
5
37
  const { buildOwnerAuthHeaders, printEnvelope } = deps;
6
38
 
@@ -9,7 +41,7 @@ export function createConsoleMandateCommands(deps) {
9
41
  flags,
10
42
  'Missing --auth-token/--owner-session-token for console mandate status',
11
43
  );
12
- const chainId = Number(flags.chainId || 8453);
44
+ const chainId = resolveConsoleMandateChainId(flags);
13
45
  const walletAddress = String(flags.walletAddress || flags.ownerAddress || '').trim();
14
46
  const query = new URLSearchParams({ chainId: String(chainId) });
15
47
  if (walletAddress) query.set('walletAddress', walletAddress);
@@ -25,7 +57,7 @@ export function createConsoleMandateCommands(deps) {
25
57
  code: 'CONSOLE_MANDATE_STATUS',
26
58
  message: 'Console delegated execution status',
27
59
  data: response?.data || response,
28
- meta: { apiBase: ctx.apiBase },
60
+ meta: { apiBase: ctx.apiBase, chainId },
29
61
  });
30
62
  }
31
63
 
@@ -36,7 +68,7 @@ export function createConsoleMandateCommands(deps) {
36
68
  );
37
69
  const payload = {
38
70
  ownerAddress: requireFlag(flags, 'ownerAddress', 'Missing --owner-address'),
39
- chainId: Number(flags.chainId || 8453),
71
+ chainId: resolveConsoleMandateChainId(flags),
40
72
  maxUsdPerDay: Number(requireFlag(flags, 'maxUsdPerDay', 'Missing --max-usd-per-day')),
41
73
  expirySeconds: Number(flags.expirySeconds || 30 * 24 * 60 * 60),
42
74
  tokenAddress: flags.tokenAddress,
@@ -54,7 +86,7 @@ export function createConsoleMandateCommands(deps) {
54
86
  code: 'CONSOLE_MANDATE_DRAFT',
55
87
  message: 'Console mandate draft created',
56
88
  data: response?.data || response,
57
- meta: { apiBase: ctx.apiBase },
89
+ meta: { apiBase: ctx.apiBase, chainId: payload.chainId },
58
90
  });
59
91
  }
60
92
 
@@ -65,7 +97,7 @@ export function createConsoleMandateCommands(deps) {
65
97
  );
66
98
  const payload = {
67
99
  walletAddress: requireFlag(flags, 'walletAddress', 'Missing --wallet-address'),
68
- chainId: Number(flags.chainId || 8453),
100
+ chainId: resolveConsoleMandateChainId(flags),
69
101
  delegationManager: requireFlag(flags, 'delegationManager', 'Missing --delegation-manager'),
70
102
  delegation: JSON.parse(requireFlag(flags, 'delegation', 'Missing --delegation JSON')),
71
103
  signature: requireFlag(flags, 'signature', 'Missing --signature'),
@@ -86,7 +118,7 @@ export function createConsoleMandateCommands(deps) {
86
118
  code: 'CONSOLE_MANDATE_ACTIVATED',
87
119
  message: 'Console mandate activated',
88
120
  data: response?.data || response,
89
- meta: { apiBase: ctx.apiBase },
121
+ meta: { apiBase: ctx.apiBase, chainId: payload.chainId },
90
122
  });
91
123
  }
92
124
 
@@ -97,7 +129,7 @@ export function createConsoleMandateCommands(deps) {
97
129
  );
98
130
  const payload = {
99
131
  walletAddress: flags.walletAddress,
100
- chainId: Number(flags.chainId || 8453),
132
+ chainId: resolveConsoleMandateChainId(flags),
101
133
  reason: flags.reason || 'cli_revoked',
102
134
  };
103
135
  const response = await apiPost(ctx, '/api/v1/console/delegation/revoke', payload, {
@@ -112,7 +144,7 @@ export function createConsoleMandateCommands(deps) {
112
144
  code: 'CONSOLE_MANDATE_REVOKED',
113
145
  message: 'Console mandate revoked',
114
146
  data: response?.data || response,
115
- meta: { apiBase: ctx.apiBase },
147
+ meta: { apiBase: ctx.apiBase, chainId: payload.chainId },
116
148
  });
117
149
  }
118
150
 
@@ -1,5 +1,6 @@
1
1
  import { apiGet, apiPost } from '../core/http.mjs';
2
2
  import { parseJsonFlag } from '../core/args.mjs';
3
+ import { negotiateCapabilities } from '../core/http.mjs';
3
4
  import { resolveConfigAgentKey } from './polymarket.mjs';
4
5
 
5
6
  function orgIdFromFlags(flags) {
@@ -10,7 +11,26 @@ function agentApiKeyFromFlags(flags, ctx) {
10
11
  return String(flags.agentApiKey || flags.agent_api_key || ctx?.agentApiKey || '').trim();
11
12
  }
12
13
 
13
- export function createHummingbotCommands({ printEnvelope }) {
14
+ function userDidFromFlags(flags) {
15
+ return String(flags.userDid || flags.user_did || '').trim();
16
+ }
17
+
18
+ function runtimeIdFromFlags(flags) {
19
+ return String(flags.runtimeId || flags.runtime_id || '').trim();
20
+ }
21
+
22
+ function failMissingIdentity(printEnvelope, ctx, message) {
23
+ printEnvelope({
24
+ success: false,
25
+ code: 'MISSING_AUTH',
26
+ message,
27
+ data: {},
28
+ meta: { apiBase: ctx.apiBase },
29
+ });
30
+ process.exit(1);
31
+ }
32
+
33
+ export function createHummingbotCommands({ printEnvelope, commandRun }) {
14
34
  async function commandHummingbotStatus(ctx, flags) {
15
35
  const orgId = orgIdFromFlags(flags);
16
36
  const agentApiKey = agentApiKeyFromFlags(flags, ctx);
@@ -40,16 +60,14 @@ export function createHummingbotCommands({ printEnvelope }) {
40
60
  async function commandHummingbotExecutorCreate(ctx, flags) {
41
61
  const orgId = orgIdFromFlags(flags);
42
62
  const agentApiKey = agentApiKeyFromFlags(flags, ctx);
43
- const userDid = String(flags.userDid || flags.user_did || '').trim();
63
+ const userDid = userDidFromFlags(flags);
44
64
  const params = parseJsonFlag(flags, 'params') || {};
45
65
  if (!agentApiKey || !userDid) {
46
- printEnvelope({
47
- success: false,
48
- code: 'MISSING_AUTH',
49
- message: 'Provide --agent-api-key and --user-did for governed executor create',
50
- data: {},
51
- });
52
- process.exit(1);
66
+ failMissingIdentity(
67
+ printEnvelope,
68
+ ctx,
69
+ 'Provide --agent-api-key and --user-did for governed executor create'
70
+ );
53
71
  }
54
72
  const body = {
55
73
  ...params,
@@ -60,6 +78,9 @@ export function createHummingbotCommands({ printEnvelope }) {
60
78
  estimatedAmountUsd: Number(flags.estimatedAmountUsd || params.estimatedAmountUsd || 0),
61
79
  type: flags.executorType || flags.executor_type || params.type || 'position_executor',
62
80
  };
81
+ if (runtimeIdFromFlags(flags)) {
82
+ body.runtimeId = runtimeIdFromFlags(flags);
83
+ }
63
84
  const data = await apiPost(
64
85
  ctx,
65
86
  '/api/v1/agent/hummingbot/executors',
@@ -69,11 +90,91 @@ export function createHummingbotCommands({ printEnvelope }) {
69
90
  printEnvelope({ success: true, data, meta: { apiBase: ctx.apiBase, orgId } });
70
91
  }
71
92
 
93
+ async function commandHummingbotExecutorStop(ctx, flags) {
94
+ const orgId = orgIdFromFlags(flags);
95
+ const agentApiKey = agentApiKeyFromFlags(flags, ctx);
96
+ const userDid = userDidFromFlags(flags);
97
+ const executorId = String(flags.executorId || flags.executor_id || '').trim();
98
+ const params = parseJsonFlag(flags, 'params') || {};
99
+ if (!agentApiKey || !userDid) {
100
+ failMissingIdentity(printEnvelope, ctx, 'Provide --agent-api-key and --user-did for governed executor stop');
101
+ }
102
+ if (!executorId) {
103
+ printEnvelope({
104
+ success: false,
105
+ code: 'MISSING_EXECUTOR_ID',
106
+ message: 'Provide --executor-id for governed executor stop',
107
+ data: {},
108
+ meta: { apiBase: ctx.apiBase, orgId },
109
+ });
110
+ process.exit(1);
111
+ }
112
+ const body = {
113
+ ...params,
114
+ orgId,
115
+ userDid,
116
+ };
117
+ if (runtimeIdFromFlags(flags)) {
118
+ body.runtimeId = runtimeIdFromFlags(flags);
119
+ }
120
+ const data = await apiPost(
121
+ ctx,
122
+ `/api/v1/agent/hummingbot/executors/${encodeURIComponent(executorId)}/stop`,
123
+ body,
124
+ { 'x-agent-api-key': agentApiKey }
125
+ );
126
+ printEnvelope({ success: true, data, meta: { apiBase: ctx.apiBase, orgId, executorId } });
127
+ }
128
+
129
+ async function runHummingbotGatewayCatalogRead(ctx, flags, action) {
130
+ if (!commandRun) {
131
+ printEnvelope({
132
+ success: false,
133
+ code: 'COMMAND_RUN_UNAVAILABLE',
134
+ message: 'Gateway catalog reads require the agent run handler',
135
+ data: {},
136
+ meta: { apiBase: ctx.apiBase },
137
+ });
138
+ process.exit(1);
139
+ }
140
+ const agentApiKey = agentApiKeyFromFlags(flags, ctx);
141
+ const userDid = userDidFromFlags(flags);
142
+ if (!agentApiKey || !userDid) {
143
+ failMissingIdentity(
144
+ printEnvelope,
145
+ ctx,
146
+ 'Provide --agent-api-key and --user-did for Gateway discovery reads'
147
+ );
148
+ }
149
+ const capabilities = await negotiateCapabilities(ctx);
150
+ if (!flags.runMode) flags.runMode = 'thirdfy';
151
+ flags.provider = 'hummingbot';
152
+ flags.action = action;
153
+ const params = parseJsonFlag(flags, 'params') || {};
154
+ flags.params = JSON.stringify({
155
+ orgId: orgIdFromFlags(flags),
156
+ ...(runtimeIdFromFlags(flags) ? { runtimeId: runtimeIdFromFlags(flags) } : {}),
157
+ ...params,
158
+ });
159
+ await commandRun(ctx, flags, capabilities);
160
+ }
161
+
162
+ async function commandHummingbotGatewayNetworks(ctx, flags) {
163
+ await runHummingbotGatewayCatalogRead(ctx, flags, 'get_hummingbot_gateway_networks');
164
+ }
165
+
166
+ async function commandHummingbotGatewayConnectors(ctx, flags) {
167
+ await runHummingbotGatewayCatalogRead(ctx, flags, 'get_hummingbot_gateway_connectors');
168
+ }
169
+
72
170
  return {
73
171
  commandHummingbotStatus,
74
172
  commandHummingbotConnectors,
75
173
  commandHummingbotExecutorSchema,
76
174
  commandHummingbotExecutorCreate,
175
+ commandHummingbotExecutorStop,
176
+ commandHummingbotGatewayNetworks,
177
+ commandHummingbotGatewayConnectors,
77
178
  resolveHummingbotAgentKey: resolveConfigAgentKey,
78
179
  };
79
180
  }
@@ -2,6 +2,7 @@ export { createPolymarketCommands, resolveConfigAgentKey } from './polymarket.mj
2
2
  export { createHyperliquidHelpers } from './hyperliquid.mjs';
3
3
  export { createLighterHelpers } from './lighter.mjs';
4
4
  export { createHummingbotCommands } from './hummingbot.mjs';
5
+ export { createCondorCommands } from './condor.mjs';
5
6
  export { createExecuteCommands } from './execute.mjs';
6
7
  export { createWalletCommands } from './wallet.mjs';
7
8
  export { createDelegationCommands } from './delegation.mjs';
@@ -14,6 +14,11 @@ const READ_ONLY_EXACT = new Set([
14
14
  'dogeos_laika_read_contract',
15
15
  'dogeos_laika_token_state',
16
16
  'prepare_polymarket_onboarding',
17
+ 'create_polymarket_bridge_deposit',
18
+ 'create_polymarket_bridge_withdraw',
19
+ 'get_condor_policy_status',
20
+ 'get_hummingbot_gateway_networks',
21
+ 'get_hummingbot_gateway_connectors',
17
22
  ]);
18
23
 
19
24
  export function normalizeActionKey(actionKey) {
@@ -19,13 +19,21 @@ const OFFCHAIN_VENUE_ORDER_ACTIONS = new Set([
19
19
  'update-lighter-margin',
20
20
  'place_polymarket_order',
21
21
  'place-polymarket-order',
22
+ 'hummingbot_executor_create',
23
+ 'hummingbot-executor-create',
24
+ 'hummingbot_executor_stop',
25
+ 'hummingbot-executor-stop',
26
+ 'condor_executor_create',
27
+ 'condor-executor-create',
28
+ 'condor_executor_stop',
29
+ 'condor-executor-stop',
22
30
  ]);
23
31
  function enforceOffchainVenueLaneCompatibility(action, runMode) {
24
32
  const normalizedAction = String(action || '').trim().toLowerCase();
25
33
  if (runMode !== 'self' || !OFFCHAIN_VENUE_ORDER_ACTIONS.has(normalizedAction)) return;
26
34
  throw createCliError(
27
35
  'OFFCHAIN_VENUE_ORDER_SELF_UNSUPPORTED',
28
- 'Polymarket CLOB, Hyperliquid perps, and Lighter perps orders are offchain signed API actions, not EVM build-tx actions. Use self for setup/funding signatures, then run venue orders with --run-mode thirdfy, --run-mode hybrid, or --run-mode agent_wallet.',
36
+ 'Polymarket CLOB, Hyperliquid perps, Lighter perps, Hummingbot executor, and Condor executor actions are offchain signed API actions, not EVM build-tx actions. Use self for setup/funding signatures, then run venue orders with --run-mode thirdfy, --run-mode hybrid, or --run-mode agent_wallet.',
29
37
  {
30
38
  recommendedRunModes: ['thirdfy', 'hybrid', 'agent_wallet'],
31
39
  setupOnlyRunMode: 'self',
@@ -1,6 +1,7 @@
1
1
  import { negotiateCapabilities } from '../core/http.mjs';
2
2
  import { createPolymarketCommands } from '../commands/polymarket.mjs';
3
3
  import { createHummingbotCommands } from '../commands/hummingbot.mjs';
4
+ import { createCondorCommands } from '../commands/condor.mjs';
4
5
  import { createHyperliquidHelpers } from '../commands/hyperliquid.mjs';
5
6
  import { createLighterHelpers } from '../commands/lighter.mjs';
6
7
  import { createExecuteCommands } from '../commands/execute.mjs';
@@ -177,6 +178,12 @@ export function createRuntimeHandlers(deps) {
177
178
 
178
179
  const __hummingbot = createHummingbotCommands({
179
180
  printEnvelope,
181
+ commandRun: __execute.commandRun,
182
+ });
183
+
184
+ const __condor = createCondorCommands({
185
+ commandRun: __execute.commandRun,
186
+ printEnvelope,
180
187
  });
181
188
 
182
189
  const __bootstrap = createBootstrapCommands({
@@ -201,6 +208,7 @@ export function createRuntimeHandlers(deps) {
201
208
  ...__consoleMandate,
202
209
  ...__polymarket,
203
210
  ...__hummingbot,
211
+ ...__condor,
204
212
  ...__bootstrap,
205
213
  ...__discovery,
206
214
  ...__telemetry,
@@ -248,6 +248,8 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
248
248
  'get_polymarket_order',
249
249
  'get_polymarket_user_orders',
250
250
  'get_polymarket_user_positions',
251
+ 'get_polymarket_bridge_supported_assets',
252
+ 'get_polymarket_bridge_status',
251
253
  ],
252
254
  discoveryFlow: [
253
255
  'get_polymarket_tags or search_polymarket',
@@ -255,7 +257,10 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
255
257
  'get_polymarket_market or get_polymarket_markets',
256
258
  'get_polymarket_order_book',
257
259
  'get_polymarket_prices or get_polymarket_price_history',
258
- 'get_polymarket_setup_status and get_polymarket_onboarding_plan before place_polymarket_order',
260
+ 'get_polymarket_funding_status with agentKey (check deposit pUSD + nested setup status)',
261
+ 'when Base USDC is on execution wallet: create_polymarket_bridge_deposit then execute_polymarket_bridge_deposit with confirm=true',
262
+ 'get_polymarket_bridge_status until pUSD lands',
263
+ 'get_polymarket_setup_status with agentKey (check liveOrderReady + apiExecutionGeoblockReady) before place_polymarket_order',
259
264
  ],
260
265
  orderManagementActions: [
261
266
  'place_polymarket_order',
@@ -267,6 +272,8 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
267
272
  setupActions: [
268
273
  'get_polymarket_setup_status',
269
274
  'get_polymarket_onboarding_plan',
275
+ 'create_polymarket_bridge_deposit',
276
+ 'execute_polymarket_bridge_deposit',
270
277
  'agent_wallet_setup:ensure_agent_wallet_deposit_wallet',
271
278
  'agent_wallet_setup:deploy_deposit_wallet_and_set_approvals',
272
279
  'agent_wallet_setup:create_or_derive_clob_credentials',
@@ -281,15 +288,18 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
281
288
  ],
282
289
  recoveryActions: [
283
290
  'get_polymarket_recovery_status',
291
+ 'create_polymarket_bridge_withdraw',
292
+ 'execute_polymarket_bridge_withdraw',
293
+ 'get_polymarket_bridge_status',
284
294
  'withdraw_polymarket_collateral',
285
295
  ],
286
296
  decommissionExample:
287
- 'get_polymarket_recovery_status -> withdraw_polymarket_collateral -> withdraw-to-user',
297
+ 'get_polymarket_recovery_status -> create_polymarket_bridge_withdraw -> execute_polymarket_bridge_withdraw -> withdraw-to-user',
288
298
  credentialType: 'polymarket_clob',
289
299
  credentialUx:
290
300
  'Autonomous agents use an agent-owned Privy wallet and Polymarket deposit wallet first: Thirdfy creates the agent wallet, deploys/approves the deposit wallet, and stores encrypted CLOB credentials once Polymarket key creation is available. User-owned browser setup remains optional for interactive capital.',
291
301
  funding:
292
- 'Fund the agent-owned Polymarket deposit wallet with Polygon pUSD after deployment and approvals. If users start with Base USDC, route Base USDC -> Polygon pUSD to the deposit wallet recipient before CLOB order placement.',
302
+ 'Fund the agent-owned Polymarket deposit wallet with Polygon pUSD after deployment and approvals. If users start with Base USDC, use Polymarket official Bridge (create/execute_polymarket_bridge_deposit). Li.Fi is legacy fallback only.',
293
303
  laneCompatibility:
294
304
  'Use agent_wallet as the preferred autonomous-agent path. Use self only for user-owned setup/funding signatures. CLOB orders should use thirdfy, hybrid, or agent_wallet after polymarket_clob credentials are stored.',
295
305
  setupBlockers: [
@@ -484,12 +494,45 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
484
494
  readActions: ['get_yield_xyz_opportunities', 'get_earning_opportunities', 'get_earn_opportunities', 'get_earn_provider', 'get_earn_position'],
485
495
  orderManagementActions: ['deposit_earn_position', 'withdraw_earn_position'],
486
496
  laneCompatibility:
487
- '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.',
497
+ 'Yield.xyz writes are transaction-prep first. Always discover with get_yield_xyz_opportunities (or get_earning_opportunities) and pass the canonical opportunityId/yieldId. Thirdfy prepareDeposit calls GET /v1/yields/{yieldId} before enter/exit, then validates unsigned transactions with @yieldxyz/shield. Balances omit metadata.name; use yields_get / get_earn_position enrich for display names.',
488
498
  example:
489
- '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}\'',
499
+ 'thirdfy-agent run --action get_yield_xyz_opportunities --params \'{"chainId":8453,"asset":"USDC"}\' && thirdfy-agent preflight --action deposit_earn_position --params \'{"providerId":"yield-xyz","opportunityId":"<canonical-yieldId>","tokenAddress":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"10","chainId":8453}\'',
490
500
  supportedChains: [1, 10, 100, 130, 137, 42220, 8453, 42161, 4663],
491
501
  };
492
502
  }
503
+ if (provider === 'hummingbot') {
504
+ return {
505
+ provider,
506
+ category: 'hummingbot',
507
+ canonicalWriteAction: 'hummingbot_executor_create',
508
+ readActions: [
509
+ 'get_hummingbot_connectors',
510
+ 'get_hummingbot_executor_schema',
511
+ 'get_hummingbot_gateway_networks',
512
+ 'get_hummingbot_gateway_connectors',
513
+ ],
514
+ orderManagementActions: ['hummingbot_executor_create', 'hummingbot_executor_stop'],
515
+ setupActions: ['get_hummingbot_connectors', 'get_hummingbot_gateway_networks', 'get_hummingbot_gateway_connectors'],
516
+ laneCompatibility:
517
+ 'Hummingbot executor create/stop and Gateway reads are offchain API actions. Use thirdfy, hybrid, or agent_wallet for writes; self is setup-only.',
518
+ example:
519
+ 'thirdfy-agent hummingbot gateway-networks && thirdfy-agent hummingbot executor-stop --executor-id <id>',
520
+ };
521
+ }
522
+ if (provider === 'condor') {
523
+ return {
524
+ provider,
525
+ category: 'condor',
526
+ canonicalWriteAction: 'condor_executor_create',
527
+ readActions: ['get_condor_policy_status'],
528
+ orderManagementActions: ['condor_executor_create', 'condor_executor_stop'],
529
+ setupActions: ['get_condor_policy_status'],
530
+ laneCompatibility:
531
+ 'Condor Pattern A reserves day notional before executor create. Use thirdfy or agent_wallet for writes; run condor preflight for governance reservation.',
532
+ example:
533
+ 'thirdfy-agent condor policy-status && thirdfy-agent condor preflight --estimated-amount-usd 25 --idempotency-key <key>',
534
+ };
535
+ }
493
536
  if (provider === 'market-data') {
494
537
  return {
495
538
  provider,