@thirdfy/agent-cli 0.2.39 → 0.2.41
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.41] - 2026-07-28
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `--provider lifi` soft-matches catalog `providerId: bridge` for `get_bridge_quote` / `execute_bridge` (historical pack taxonomy) while still matching real trade provider `lifi` (Robinhood 4663). Preferred flag remains `--provider bridge`. MCP parity in `thirdfy-mcp` **0.0.84**.
|
|
12
|
+
|
|
13
|
+
## [0.2.40] - 2026-07-27
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- EarnClaw runtime Polymarket write gate: when `EARNCLAW_RUNTIME_ID` or `THIRDFY_EXECUTION_RUNTIME_ID` is set, `place_polymarket_order` / `place_prediction_order` require `idempotencyKey` starting with `earnclaw:<runtimeId>`. Blocks bare CLI/dashboard tool buys on managed Hermes machines. MCP parity in `thirdfy-mcp` **0.0.83**.
|
|
18
|
+
|
|
7
19
|
## [0.2.39] - 2026-07-27
|
|
8
20
|
|
|
9
21
|
### Changed
|
package/README.md
CHANGED
|
@@ -40,13 +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
|
+
## What's new in v0.2.41
|
|
44
|
+
- `--provider lifi` soft-matches catalog `providerId: bridge` for bridge quote/execute (historical pack flag) while still matching trade provider `lifi` on Robinhood 4663. Prefer `--provider bridge` for bridges.
|
|
45
|
+
- See [CHANGELOG.md](./CHANGELOG.md) for older versions.
|
|
44
46
|
|
|
45
|
-
- Morpho hints: Base MetaMorpho V1 writes on `8453`; Robinhood Vault V2 on `4663` is discoverable read-only until `maxDeposit > 0`. Prefer `depositPlan` from `get_earn_opportunities`.
|
|
46
|
-
- Updated [`docs/providers/earn-morpho.md`](./docs/providers/earn-morpho.md) for GraphQL discovery and V1 vs V2 behavior.
|
|
47
|
-
- Pairs with `thirdfy-mcp` **0.0.82** and Thirdfy API develop (Morpho GraphQL integration).
|
|
48
|
-
|
|
49
|
-
Older versions: see [CHANGELOG.md](./CHANGELOG.md) and [GitHub Releases](https://github.com/thirdfy/agent-cli/releases).
|
|
50
47
|
|
|
51
48
|
## Quick start
|
|
52
49
|
|
package/package.json
CHANGED
|
@@ -239,6 +239,14 @@ function actionMatchesProvider(action, requestedProvider, allActions) {
|
|
|
239
239
|
if (provider === 'hyperliquid' || provider === 'lighter') return false;
|
|
240
240
|
return isProviderActionKey(action, 'bridge');
|
|
241
241
|
}
|
|
242
|
+
// Soft-compat: packs historically used --provider lifi for Li.Fi bridge. Catalog providerId is bridge.
|
|
243
|
+
// Still match real trade providerId lifi (Robinhood 4663 spot). Do not remap normalizeProviderId globally.
|
|
244
|
+
if (requestedProvider === 'lifi') {
|
|
245
|
+
if (provider === 'lifi') return true;
|
|
246
|
+
if (provider === 'hyperliquid' || provider === 'lighter') return false;
|
|
247
|
+
if (provider === 'bridge' || isProviderActionKey(action, 'bridge')) return true;
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
242
250
|
if (requestedProvider.startsWith('dogeos')) return isProviderActionKey(action, requestedProvider);
|
|
243
251
|
if (requestedProvider === 'earn') {
|
|
244
252
|
return provider === 'earn' || provider === 'morpho' || provider === 'aegis' || provider === 'curve' || provider === 'capyfi' || provider === 'vaults-fyi' || provider === 'yield-xyz' || isEarnCatalogAction(action);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createCliError } from '../../core/envelope.mjs';
|
|
2
|
+
|
|
3
|
+
function readUuid(value) {
|
|
4
|
+
const trimmed = String(value || '').trim();
|
|
5
|
+
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)
|
|
6
|
+
? trimmed
|
|
7
|
+
: undefined;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const POLYMARKET_PLACE_ACTIONS = new Set([
|
|
11
|
+
'place_polymarket_order',
|
|
12
|
+
'place-polymarket-order',
|
|
13
|
+
'place_prediction_order',
|
|
14
|
+
'place-prediction-order',
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
export function resolveEarnclawRuntimeId(env = process.env) {
|
|
18
|
+
const runtimeId = readUuid(env.THIRDFY_EXECUTION_RUNTIME_ID)
|
|
19
|
+
|| readUuid(env.EARNCLAW_RUNTIME_ID);
|
|
20
|
+
return runtimeId ? runtimeId.toLowerCase() : '';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function normalizePolymarketPlaceAction(action) {
|
|
24
|
+
return String(action || '')
|
|
25
|
+
.trim()
|
|
26
|
+
.toLowerCase()
|
|
27
|
+
.replace(/_/g, '-');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function isPolymarketPlaceAction(action) {
|
|
31
|
+
const key = String(action || '').trim().toLowerCase();
|
|
32
|
+
if (POLYMARKET_PLACE_ACTIONS.has(key)) return true;
|
|
33
|
+
return normalizePolymarketPlaceAction(key) === 'place-polymarket-order'
|
|
34
|
+
|| normalizePolymarketPlaceAction(key) === 'place-prediction-order';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* On EarnClaw-managed Hermes machines, ad-hoc CLI/MCP/dashboard tool calls can
|
|
39
|
+
* place Polymarket orders without pack execute-gate. Require an earnclaw-scoped
|
|
40
|
+
* idempotency key so only adapter/operator keys pass.
|
|
41
|
+
*/
|
|
42
|
+
export function assertEarnclawPolymarketWriteIdempotency({
|
|
43
|
+
action,
|
|
44
|
+
idempotencyKey,
|
|
45
|
+
paramsIdempotencyKey,
|
|
46
|
+
env = process.env,
|
|
47
|
+
} = {}) {
|
|
48
|
+
if (!isPolymarketPlaceAction(action)) return null;
|
|
49
|
+
const runtimeId = resolveEarnclawRuntimeId(env);
|
|
50
|
+
if (!runtimeId) return null;
|
|
51
|
+
|
|
52
|
+
const prefix = `earnclaw:${runtimeId}`;
|
|
53
|
+
const keys = [idempotencyKey, paramsIdempotencyKey]
|
|
54
|
+
.map((key) => String(key || '').trim())
|
|
55
|
+
.filter(Boolean);
|
|
56
|
+
if (keys.some((key) => key.toLowerCase().startsWith(prefix))) return null;
|
|
57
|
+
|
|
58
|
+
throw createCliError(
|
|
59
|
+
'EARNCLAW_PM_IDEMPOTENCY_REQUIRED',
|
|
60
|
+
`EarnClaw runtime ${runtimeId} requires Polymarket place orders to use idempotencyKey starting with "${prefix}". ` +
|
|
61
|
+
'Pack execute-gate and operator exits set this automatically. Bare CLI/dashboard tool writes are blocked.',
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -3,6 +3,7 @@ import { requireFlag, parseJsonFlag } from '../../core/args.mjs';
|
|
|
3
3
|
import { loadProfileConfig } from '../../core/context.mjs';
|
|
4
4
|
import { createCliError } from '../../core/envelope.mjs';
|
|
5
5
|
import { normalizeRunMode, normalizeManagedRunMode, normalizeHybridWalletMode } from '../../core/runMode.mjs';
|
|
6
|
+
import { assertEarnclawPolymarketWriteIdempotency } from './earnclawRuntimeWriteGate.mjs';
|
|
6
7
|
export function createExecutionPayloads({ getPreparedParams, rawUnitsToDecimalString }) {
|
|
7
8
|
function buildBuildTxPayload(flags, resolvedAction) {
|
|
8
9
|
const runMode = String(flags.runMode || '').trim().toLowerCase() || 'self';
|
|
@@ -125,6 +126,11 @@ function buildManagedExecutePayload(flags, options) {
|
|
|
125
126
|
} else if (flags.idempotencyKey) {
|
|
126
127
|
payload.executionIdempotencyKey = String(flags.idempotencyKey);
|
|
127
128
|
}
|
|
129
|
+
assertEarnclawPolymarketWriteIdempotency({
|
|
130
|
+
action: payload.action,
|
|
131
|
+
idempotencyKey: payload.executionIdempotencyKey,
|
|
132
|
+
paramsIdempotencyKey: managedParams?.idempotencyKey,
|
|
133
|
+
});
|
|
128
134
|
return payload;
|
|
129
135
|
}
|
|
130
136
|
|
|
@@ -171,6 +177,13 @@ function buildIntentPayload(flags, options) {
|
|
|
171
177
|
} else if (flags.idempotencyKey) {
|
|
172
178
|
payload.idempotencyKey = String(flags.idempotencyKey);
|
|
173
179
|
}
|
|
180
|
+
if (!options.validationOnly) {
|
|
181
|
+
assertEarnclawPolymarketWriteIdempotency({
|
|
182
|
+
action: payload.action,
|
|
183
|
+
idempotencyKey: payload.idempotencyKey,
|
|
184
|
+
paramsIdempotencyKey: payload.params?.idempotencyKey,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
174
187
|
return payload;
|
|
175
188
|
}
|
|
176
189
|
|