@thirdfy/agent-cli 0.2.70 → 0.2.72

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,18 @@ All notable changes to `@thirdfy/agent-cli` are documented here. The format is b
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.2.72] - 2026-09-17
8
+
9
+ ### Added
10
+
11
+ - 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**.
12
+
13
+ ## [0.2.71] - 2026-09-16
14
+
15
+ ### Fixed
16
+
17
+ - `get_avantis_setup_status` / `get_avantis_onboarding_plan` use the 180s compose timeout. Empty queued `/execute-intent` fallbacks fail as `MANAGED_READ_EMPTY_EXECUTE_INTENT` instead of a successful empty setup payload. Pin: `test/actionTimeouts.test.cjs`, `test/agent-wallet-readonly-fallback.test.cjs`. Matches `thirdfy-mcp` **0.0.121**.
18
+
7
19
  ## [0.2.70] - 2026-09-16
8
20
 
9
21
  ### Fixed
package/README.md CHANGED
@@ -40,10 +40,9 @@ Run without global install:
40
40
  npx @thirdfy/agent-cli --help
41
41
  ```
42
42
 
43
- ## What's new in v0.2.70
43
+ ## What's new in v0.2.72
44
44
 
45
- - `--action get_aave_markets` resolves to the first-class catalog key before colliding earn aliases.
46
- - Hosted runtime write keys stay scoped by runtime UUID so Thirdfy action events can join.
45
+ - Hyperliquid `place_hyperliquid_tp_sl` is a write. Lighter `place_lighter_perps_order` accepts stop-loss and take-profit `orderType` values with `triggerPrice`.
47
46
  - See [CHANGELOG.md](./CHANGELOG.md) and GitHub Releases for older versions.
48
47
 
49
48
  ## Quick start
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdfy/agent-cli",
3
- "version": "0.2.70",
3
+ "version": "0.2.72",
4
4
  "description": "Thirdfy Agent CLI for onboarding, governance preflight, execute-intent, and status polling.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,6 +2,8 @@ import { DEFAULT_TIMEOUT_MS } from './constants.mjs';
2
2
 
3
3
  const LONG_RUNNING_ACTIONS = new Set([
4
4
  'complete_avantis_onboarding',
5
+ 'get_avantis_setup_status',
6
+ 'get_avantis_onboarding_plan',
5
7
  'complete_lighter_onboarding',
6
8
  'setup_lighter_api_key',
7
9
  'register_lighter_api_key',
@@ -23,7 +25,7 @@ function normalizeActionId(action) {
23
25
  .toLowerCase();
24
26
  }
25
27
 
26
- /** Longer HTTP timeout for Lighter onboarding and Morpho/Aave earn writes (approve + vault call). */
28
+ /** Longer HTTP timeout for Avantis/Lighter onboarding, Avantis setup-status compose, and Morpho/Aave earn writes. */
27
29
  export function resolveActionTimeoutMs(action, baseTimeoutMs = DEFAULT_TIMEOUT_MS) {
28
30
  const base = Number.isFinite(baseTimeoutMs) && baseTimeoutMs > 0 ? baseTimeoutMs : DEFAULT_TIMEOUT_MS;
29
31
  if (!LONG_RUNNING_ACTIONS.has(normalizeActionId(action))) return base;
@@ -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',
@@ -12,6 +12,20 @@ export function managedReadExecuteErrorText(data) {
12
12
  return String(data?.error || data?.message || data?.code || data?.blockedReason || '').toLowerCase();
13
13
  }
14
14
 
15
+ export function isEmptyQueuedExecuteIntent(data) {
16
+ const rec = data && typeof data === 'object' && !Array.isArray(data) ? data : null;
17
+ if (!rec) return false;
18
+ // Read payloads live in `data`. Do not mix those fields with outer batch defaults —
19
+ // `normalizeIntentResponse` materializes status=queued, executed=0, results=[].
20
+ const nested = rec.data && typeof rec.data === 'object' && !Array.isArray(rec.data) ? rec.data : rec;
21
+ const status = String(nested.status ?? '').toLowerCase();
22
+ const executed = Number(nested.executed);
23
+ const results = nested.results;
24
+ const emptyResults = Array.isArray(results) && results.length === 0;
25
+ const queued = status === 'queued' || (Number.isFinite(executed) && executed === 0);
26
+ return queued && emptyResults;
27
+ }
28
+
15
29
  export function shouldFallbackManagedReadToExecuteIntent({ isReadOnly, errorText } = {}) {
16
30
  if (!isReadOnly) return false;
17
31
  const err = String(errorText || '').toLowerCase();
@@ -12,7 +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 { shouldFallbackManagedReadToExecuteIntent } from './managedReadExecuteRail.mjs';
15
+ import { isEmptyQueuedExecuteIntent, shouldFallbackManagedReadToExecuteIntent } from './managedReadExecuteRail.mjs';
16
16
  import { createRequire } from 'module';
17
17
 
18
18
  const require = createRequire(import.meta.url);
@@ -506,6 +506,11 @@ async function executeManagedWalletRun(ctx, flags, resolved, options) {
506
506
  const response = await apiPost(actionCtx, '/api/v1/agent/execute', payload);
507
507
  if (shouldFallbackAgentWalletToExecuteIntent(resolved, response)) {
508
508
  const intentResult = await runReadOnlyActionViaIntentRail(ctx, flags, resolved, options, preflight);
509
+ if (isEmptyQueuedExecuteIntent(intentResult.raw || intentResult)) {
510
+ intentResult.success = false;
511
+ intentResult.status = 'failed';
512
+ intentResult.error = intentResult.error || 'MANAGED_READ_EMPTY_EXECUTE_INTENT';
513
+ }
509
514
  intentResult.executionWalletAddress =
510
515
  preflight?.executionWalletAddress ||
511
516
  response?.executionWalletAddress ||
@@ -37,6 +37,7 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
37
37
  ],
38
38
  orderManagementActions: [
39
39
  'place_hyperliquid_perps_order',
40
+ 'place_hyperliquid_tp_sl',
40
41
  'cancel_hyperliquid_perps_order',
41
42
  'update_hyperliquid_leverage',
42
43
  'get_hyperliquid_open_orders',