@thirdfy/agent-cli 0.2.6 → 0.2.8

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.8] - 2026-06-13
8
+
9
+ ### Added
10
+
11
+ - EarnClaw runtime attribution on all API POSTs: reads `THIRDFY_EXECUTION_RUNTIME_ID` / `THIRDFY_EXECUTION_ORG_ID` (with `EARNCLAW_*` fallback) and sends `executionContext` plus `x-thirdfy-execution-*` headers on execute paths. Pairs with Thirdfy API v3.4.55+ for per-runtime credit debits.
12
+
13
+ ### Fixed
14
+
15
+ - `apiPost` resolves execution context headers from the request body, not env only.
16
+
17
+ ## [0.2.7] - 2026-06-08
18
+
19
+ ### Added
20
+
21
+ - Hyperliquid `update_hyperliquid_leverage` action parity: listed in provider hints `orderManagementActions`, classified under the `hyperliquid` provider, and treated as an offchain venue write (rejects `self`/BYOW with `OFFCHAIN_VENUE_ORDER_SELF_UNSUPPORTED`; use `thirdfy`/`hybrid`/`agent_wallet`). Sets per-coin leverage (cross by default), bounded by the venue per-coin maxLeverage. Matches Thirdfy API v3.4.52+ and thirdfy-mcp v0.0.56+.
22
+
7
23
  ## [0.2.6] - 2026-06-05
8
24
 
9
25
  ### Changed
package/README.md CHANGED
@@ -40,11 +40,11 @@ Run without global install:
40
40
  npx @thirdfy/agent-cli --help
41
41
  ```
42
42
 
43
- ## What's new in v0.2.6
43
+ ## What's new in v0.2.8
44
44
 
45
- - Hyperliquid provider hints include `complete_hyperliquid_onboarding` and `setupWarnings` for unfunded builder treasury (`HYPERLIQUID_BUILDER_WALLET_UNFUNDED`).
46
- - Builder fee approval is documented only when builder monetization is active (builder treasury funded on Hyperliquid).
47
- - Command reference matches Thirdfy API setup/execute parity for Hyperliquid perps.
45
+ - Hosted runtimes can set `THIRDFY_EXECUTION_RUNTIME_ID` and `THIRDFY_EXECUTION_ORG_ID` in machine env (EarnClaw also sets legacy `EARNCLAW_*` aliases). The CLI forwards neutral `executionContext` on Thirdfy API POSTs.
46
+ - Attribution uses `x-thirdfy-execution-runtime-id`, `x-thirdfy-execution-org-id`, and `executionContext` on execute payloads.
47
+ - Pairs with Thirdfy API v3.4.55+ and EarnClaw cost sync `attribution=strict`.
48
48
 
49
49
  Older versions: [CHANGELOG.md](./CHANGELOG.md) and [GitHub Releases](https://github.com/thirdfy/agent-cli/releases).
50
50
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdfy/agent-cli",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Thirdfy Agent CLI for onboarding, governance preflight, execute-intent, and status polling.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,7 @@
1
+ /** @deprecated Import from executionContext.mjs instead. */
2
+ export {
3
+ resolveExecutionContextFromEnv as resolveEarnClawAttributionFromEnv,
4
+ resolveExecutionContextFromInput as resolveEarnClawAttributionFromInput,
5
+ buildExecutionContextHeaders as buildEarnClawAttributionHeaders,
6
+ mergeExecutionContext as mergeEarnClawContext,
7
+ } from './executionContext.mjs';
@@ -0,0 +1,50 @@
1
+ function readUuid(value) {
2
+ const trimmed = String(value || '').trim();
3
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(trimmed)
4
+ ? trimmed
5
+ : undefined;
6
+ }
7
+
8
+ export function resolveExecutionContextFromEnv() {
9
+ const runtimeId = readUuid(process.env.THIRDFY_EXECUTION_RUNTIME_ID)
10
+ || readUuid(process.env.EARNCLAW_RUNTIME_ID);
11
+ const orgId = readUuid(process.env.THIRDFY_EXECUTION_ORG_ID)
12
+ || readUuid(process.env.EARNCLAW_ORG_ID);
13
+ return { runtimeId, orgId };
14
+ }
15
+
16
+ export function resolveExecutionContextFromInput(input = {}) {
17
+ const env = resolveExecutionContextFromEnv();
18
+ const executionContext = input.executionContext && typeof input.executionContext === 'object'
19
+ ? input.executionContext
20
+ : {};
21
+ const context = input.context && typeof input.context === 'object' ? input.context : {};
22
+ const runtimeId = readUuid(input.runtimeId)
23
+ || readUuid(executionContext.runtimeId)
24
+ || readUuid(context.runtimeId)
25
+ || env.runtimeId;
26
+ const orgId = readUuid(input.orgId)
27
+ || readUuid(executionContext.orgId)
28
+ || readUuid(context.orgId)
29
+ || env.orgId;
30
+ return { runtimeId, orgId };
31
+ }
32
+
33
+ export function buildExecutionContextHeaders(attribution) {
34
+ const headers = {};
35
+ if (attribution.runtimeId) headers['x-thirdfy-execution-runtime-id'] = attribution.runtimeId;
36
+ if (attribution.orgId) headers['x-thirdfy-execution-org-id'] = attribution.orgId;
37
+ return headers;
38
+ }
39
+
40
+ export function mergeExecutionContext(body) {
41
+ const attribution = resolveExecutionContextFromInput(body);
42
+ if (!attribution.runtimeId && !attribution.orgId) return body;
43
+ const executionContext = body.executionContext && typeof body.executionContext === 'object'
44
+ ? { ...body.executionContext }
45
+ : {};
46
+ if (attribution.runtimeId && !executionContext.runtimeId) executionContext.runtimeId = attribution.runtimeId;
47
+ if (attribution.orgId && !executionContext.orgId) executionContext.orgId = attribution.orgId;
48
+ if (!executionContext.source) executionContext.source = 'hosted_runtime';
49
+ return { ...body, executionContext };
50
+ }
package/src/core/http.mjs CHANGED
@@ -1,15 +1,30 @@
1
+ import {
2
+ buildExecutionContextHeaders,
3
+ mergeExecutionContext,
4
+ resolveExecutionContextFromInput,
5
+ } from './executionContext.mjs';
6
+
1
7
  export async function apiGet(ctx, route, headers = {}) {
2
- return requestJson(ctx, route, { method: 'GET', headers });
8
+ return requestJson(ctx, route, { method: 'GET', headers: mergeExecutionContextHeaders(headers) });
9
+ }
10
+
11
+ function mergeExecutionContextHeaders(headers = {}, body = {}) {
12
+ return {
13
+ ...buildExecutionContextHeaders(resolveExecutionContextFromInput(body)),
14
+ ...headers,
15
+ };
3
16
  }
4
17
 
5
18
  export async function apiPost(ctx, route, body, headers = {}) {
19
+ const normalizedBody = body && typeof body === 'object' ? body : {};
20
+ const mergedBody = mergeExecutionContext(normalizedBody);
6
21
  return requestJson(ctx, route, {
7
22
  method: 'POST',
8
23
  headers: {
9
24
  'content-type': 'application/json',
10
- ...headers,
25
+ ...mergeExecutionContextHeaders(headers, normalizedBody),
11
26
  },
12
- body: JSON.stringify(body),
27
+ body: JSON.stringify(mergedBody),
13
28
  });
14
29
  }
15
30
 
@@ -87,6 +87,7 @@ function inferActionProvider(action) {
87
87
  'deposit-hyperliquid-bridge': 'hyperliquid',
88
88
  'place-hyperliquid-perps-order': 'hyperliquid',
89
89
  'cancel-hyperliquid-perps-order': 'hyperliquid',
90
+ 'update-hyperliquid-leverage': 'hyperliquid',
90
91
  'get-perps-markets': 'hyperliquid',
91
92
  'get-perps-account': 'hyperliquid',
92
93
  'get-perps-position': 'hyperliquid',
@@ -5,6 +5,8 @@ const OFFCHAIN_VENUE_ORDER_ACTIONS = new Set([
5
5
  'place-hyperliquid-perps-order',
6
6
  'cancel_hyperliquid_perps_order',
7
7
  'cancel-hyperliquid-perps-order',
8
+ 'update_hyperliquid_leverage',
9
+ 'update-hyperliquid-leverage',
8
10
  'place_polymarket_order',
9
11
  'place-polymarket-order',
10
12
  ]);
@@ -38,6 +38,7 @@ export function createProviderHints({ getNegotiatedCapabilitiesCache }) {
38
38
  orderManagementActions: [
39
39
  'place_hyperliquid_perps_order',
40
40
  'cancel_hyperliquid_perps_order',
41
+ 'update_hyperliquid_leverage',
41
42
  'get_hyperliquid_open_orders',
42
43
  ],
43
44
  setupActions: [