@thirdfy/agent-cli 0.1.25 → 0.1.27
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 +39 -1
- package/README.md +3 -1
- package/bin/thirdfy-agent.mjs +169 -10
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,9 +4,47 @@ All notable changes to `@thirdfy/agent-cli` are documented here. The format is b
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **`npm run publish:npm:local`** (`scripts/local-npm-publish.sh`): loads gitignored `.env`, exports `NODE_AUTH_TOKEN` from `NPM_TOKEN`, then runs `release:npm` via **node** (`scripts/release-npm.mjs`, `--dry-run` or `--publish`) so the outer `npm run` does not strip registry auth before the release script runs. Documented in `docs/releasing.md` Path B.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- `release:npm`: `npm publish` now uses a short-lived `NPM_CONFIG_USERCONFIG` file with `//registry.npmjs.org/:_authToken=…` when a token is present, so npm 10+ authenticates reliably (Bearer env alone was not enough in this repo’s CLI runs).
|
|
14
|
+
- `release:npm -- --publish`: when both `NODE_AUTH_TOKEN` and `NPM_TOKEN` are set but `NODE_AUTH_TOKEN` is much shorter than `NPM_TOKEN` (common placeholder), use `NPM_TOKEN` for the publish subprocess and print a warning.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **CI:** Release workflow no longer requests `id-token: write` (npm publish uses `secrets.NPM_TOKEN` only).
|
|
19
|
+
|
|
20
|
+
## [0.1.27] - 2026-05-05
|
|
21
|
+
|
|
22
|
+
**npm:** [`@thirdfy/agent-cli@0.1.27`](https://www.npmjs.com/package/@thirdfy/agent-cli/v/0.1.27)
|
|
23
|
+
**Git tag:** [`v0.1.27`](https://github.com/thirdfy/agent-cli/releases/tag/v0.1.27)
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Maintainer [docs/releasing.md](./docs/releasing.md) runbook for npm + GitHub Actions, `.env.example` template, and `npm run release:npm` (`scripts/release-npm.mjs`) with dry-run default and stricter checks for `--publish`.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **Bugbot (PR #24):** `release:npm` maps `NPM_TOKEN` → `NODE_AUTH_TOKEN` for the publish subprocess; `npm publish` uses `--ignore-scripts` after explicit checks so `prepublishOnly` does not run twice. **Release** GitHub Action uses the same `npm publish --ignore-scripts` after its validation steps.
|
|
32
|
+
|
|
33
|
+
## [0.1.26] - 2026-05-05
|
|
34
|
+
|
|
35
|
+
**Git tag:** [`v0.1.26`](https://github.com/thirdfy/agent-cli/releases/tag/v0.1.26) — provider parity merged to `main`; not published to the npm registry (use **0.1.27** for the first npm build that includes PR #23 plus release tooling from PR #24).
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- **Provider discovery parity:** Align `actions --provider` filtering with MCP/API provider taxonomy for provider-less spot, Hyperliquid/perps, bridge, DogeOS, prediction, and earn catalog rows.
|
|
40
|
+
- **Metadata-first discovery:** Prefer API-supplied `providerId`, `domain`, and `category` for provider filtering, keeping action-name inference as a legacy fallback only.
|
|
41
|
+
- **Bugbot:** `actions --provider` key fallback now matches provider suffix patterns (e.g. `execute_bridge` for `--provider bridge`).
|
|
42
|
+
- **Bugbot:** After metadata mismatch, hyperliquid/polymarket/bridge/DogeOS branches use action-key matching only (removed redundant `provider ===` checks and dead final equality).
|
|
43
|
+
|
|
7
44
|
## [0.1.25] - 2026-05-04
|
|
8
45
|
|
|
9
|
-
**npm:** `@thirdfy/agent-cli@0.1.25`
|
|
46
|
+
**npm:** [`@thirdfy/agent-cli@0.1.25`](https://www.npmjs.com/package/@thirdfy/agent-cli/v/0.1.25)
|
|
47
|
+
**Git tag:** [`v0.1.25`](https://github.com/thirdfy/agent-cli/releases/tag/v0.1.25)
|
|
10
48
|
|
|
11
49
|
### Changed
|
|
12
50
|
|
package/README.md
CHANGED
|
@@ -40,7 +40,9 @@ npx @thirdfy/agent-cli --help
|
|
|
40
40
|
|
|
41
41
|
## Release notes
|
|
42
42
|
|
|
43
|
-
Version history and highlights: [CHANGELOG.md](./CHANGELOG.md). Recent CLI releases document
|
|
43
|
+
Version history and highlights: [CHANGELOG.md](./CHANGELOG.md). Recent CLI releases document provider discovery parity, metadata-first `actions --provider` filtering, earn deposit guards, and README refresh through **v0.1.27**.
|
|
44
|
+
|
|
45
|
+
**Maintainers — npm:** follow [docs/releasing.md](./docs/releasing.md). From a clone with gitignored `.env`, use `npm run publish:npm:local -- --dry-run` then `npm run publish:npm:local`. Or run `npm run release:npm` after exporting tokens in the shell. Never commit npm tokens — use [.env.example](./.env.example) as a template only.
|
|
44
46
|
|
|
45
47
|
## Quick start
|
|
46
48
|
|
package/bin/thirdfy-agent.mjs
CHANGED
|
@@ -3228,6 +3228,172 @@ function formatActionList(items) {
|
|
|
3228
3228
|
.join(', ');
|
|
3229
3229
|
}
|
|
3230
3230
|
|
|
3231
|
+
function normalizeProviderId(value) {
|
|
3232
|
+
return String(value || '').trim().toLowerCase();
|
|
3233
|
+
}
|
|
3234
|
+
|
|
3235
|
+
function rowActionKey(action) {
|
|
3236
|
+
return getActionKey(action)
|
|
3237
|
+
.replace(/-/g, '_')
|
|
3238
|
+
.toLowerCase();
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
function canonicalActionKey(action) {
|
|
3242
|
+
return getActionKey(action)
|
|
3243
|
+
.replace(/_/g, '-')
|
|
3244
|
+
.toLowerCase();
|
|
3245
|
+
}
|
|
3246
|
+
|
|
3247
|
+
function inferActionProvider(action) {
|
|
3248
|
+
// API catalog metadata (`providerId`, `domain`, `category`) is the source of truth.
|
|
3249
|
+
// This fallback only keeps older catalog rows / older API deployments discoverable.
|
|
3250
|
+
const key = canonicalActionKey(action);
|
|
3251
|
+
const knownMap = {
|
|
3252
|
+
swap: 'trading',
|
|
3253
|
+
'execute-optimal-swap': 'trading',
|
|
3254
|
+
'get-best-trading-quote': 'trading',
|
|
3255
|
+
'dogeos-barkswap-get-quote': 'dogeos-barkswap',
|
|
3256
|
+
'dogeos-barkswap-execute-swap': 'dogeos-barkswap',
|
|
3257
|
+
'dogeos-get-ecosystem-overview': 'dogeos-ecosystem',
|
|
3258
|
+
'dogeos-get-wallet-actionability': 'dogeos-ecosystem',
|
|
3259
|
+
'dogeos-prepare-trade': 'dogeos-ecosystem',
|
|
3260
|
+
'dogeos-prepare-token-launch': 'dogeos-ecosystem',
|
|
3261
|
+
'dogeos-get-chain-insights': 'dogeos-ecosystem',
|
|
3262
|
+
'dogeos-get-trending-tokens': 'dogeos-ecosystem',
|
|
3263
|
+
'dogeos-get-new-tokens': 'dogeos-ecosystem',
|
|
3264
|
+
'dogeos-get-early-bird-tokens': 'dogeos-ecosystem',
|
|
3265
|
+
'dogeos-get-only-moon-tokens': 'dogeos-ecosystem',
|
|
3266
|
+
'dogeos-get-big-wins-tokens': 'dogeos-ecosystem',
|
|
3267
|
+
'dogeos-get-related-tokens': 'dogeos-ecosystem',
|
|
3268
|
+
'dogeos-laika-read-contract': 'dogeos-laika',
|
|
3269
|
+
'dogeos-laika-execute-raw': 'dogeos-laika',
|
|
3270
|
+
'dogeos-laika-launch-token': 'dogeos-laika',
|
|
3271
|
+
'dogeos-laika-buy-token': 'dogeos-laika',
|
|
3272
|
+
'dogeos-laika-claim': 'dogeos-laika',
|
|
3273
|
+
'dogeos-laika-token-state': 'dogeos-laika',
|
|
3274
|
+
'get-governance-v2-overview': 'governance-v2',
|
|
3275
|
+
'get-governance-v2-timeseries': 'governance-v2',
|
|
3276
|
+
'get-governance-v2-breakdowns': 'governance-v2',
|
|
3277
|
+
'get-hyperliquid-perps-meta': 'hyperliquid',
|
|
3278
|
+
'get-hyperliquid-all-mids': 'hyperliquid',
|
|
3279
|
+
'get-hyperliquid-l2-book': 'hyperliquid',
|
|
3280
|
+
'get-hyperliquid-candles': 'hyperliquid',
|
|
3281
|
+
'get-hyperliquid-user-state': 'hyperliquid',
|
|
3282
|
+
'get-hyperliquid-open-orders': 'hyperliquid',
|
|
3283
|
+
'get-hyperliquid-setup-status': 'hyperliquid',
|
|
3284
|
+
'get-hyperliquid-onboarding-plan': 'hyperliquid',
|
|
3285
|
+
'prepare-hyperliquid-onboarding': 'hyperliquid',
|
|
3286
|
+
'claim-hyperliquid-testnet-faucet': 'hyperliquid',
|
|
3287
|
+
'get-hyperliquid-builder-fee-status': 'hyperliquid',
|
|
3288
|
+
'approve-hyperliquid-agent': 'hyperliquid',
|
|
3289
|
+
'approve-hyperliquid-builder-fee': 'hyperliquid',
|
|
3290
|
+
'register-hyperliquid-referrer': 'hyperliquid',
|
|
3291
|
+
'set-hyperliquid-referrer': 'hyperliquid',
|
|
3292
|
+
'get-hyperliquid-referral-status': 'hyperliquid',
|
|
3293
|
+
'deposit-hyperliquid-staking': 'hyperliquid',
|
|
3294
|
+
'deposit-hyperliquid-bridge': 'hyperliquid',
|
|
3295
|
+
'place-hyperliquid-perps-order': 'hyperliquid',
|
|
3296
|
+
'get-perps-markets': 'hyperliquid',
|
|
3297
|
+
'get-perps-account': 'hyperliquid',
|
|
3298
|
+
'get-perps-position': 'hyperliquid',
|
|
3299
|
+
'place-perps-order': 'hyperliquid',
|
|
3300
|
+
'cancel-perps-order': 'hyperliquid',
|
|
3301
|
+
'get-earn-opportunities': 'earn',
|
|
3302
|
+
'get-earn-provider': 'earn',
|
|
3303
|
+
'get-earn-position': 'earn',
|
|
3304
|
+
'deposit-earn-position': 'earn',
|
|
3305
|
+
'withdraw-earn-position': 'earn',
|
|
3306
|
+
'get-morpho-vaults': 'morpho',
|
|
3307
|
+
'deposit-morpho-vault': 'morpho',
|
|
3308
|
+
'withdraw-morpho-vault': 'morpho',
|
|
3309
|
+
'get-curve-pools': 'curve',
|
|
3310
|
+
'get-curve-pool-details': 'curve',
|
|
3311
|
+
'deposit-curve-pool': 'curve',
|
|
3312
|
+
'withdraw-curve-pool': 'curve',
|
|
3313
|
+
'get-prediction-markets': 'polymarket',
|
|
3314
|
+
'get-prediction-market': 'polymarket',
|
|
3315
|
+
'get-prediction-order-book': 'polymarket',
|
|
3316
|
+
'get-prediction-position': 'polymarket',
|
|
3317
|
+
'place-prediction-order': 'polymarket',
|
|
3318
|
+
'cancel-prediction-order': 'polymarket',
|
|
3319
|
+
'get-polymarket-markets': 'polymarket',
|
|
3320
|
+
'get-polymarket-market': 'polymarket',
|
|
3321
|
+
'get-polymarket-setup-status': 'polymarket',
|
|
3322
|
+
'get-polymarket-order': 'polymarket',
|
|
3323
|
+
'place-polymarket-order': 'polymarket',
|
|
3324
|
+
};
|
|
3325
|
+
if (knownMap[key]) return knownMap[key];
|
|
3326
|
+
if (key.includes('hyperliquid')) return 'hyperliquid';
|
|
3327
|
+
if (key.includes('polymarket') || key.includes('prediction')) return 'polymarket';
|
|
3328
|
+
if (key.includes('morpho')) return 'morpho';
|
|
3329
|
+
if (key.includes('curve')) return 'curve';
|
|
3330
|
+
if (key.includes('earn')) return 'earn';
|
|
3331
|
+
if (key.includes('bridge')) return 'bridge';
|
|
3332
|
+
if (key.includes('dogeos-barkswap')) return 'dogeos-barkswap';
|
|
3333
|
+
if (key.includes('dogeos-laika')) return 'dogeos-laika';
|
|
3334
|
+
if (key.includes('dogeos')) return 'dogeos-ecosystem';
|
|
3335
|
+
return '';
|
|
3336
|
+
}
|
|
3337
|
+
|
|
3338
|
+
function getActionProviderWithInference(action) {
|
|
3339
|
+
return getActionProvider(action) || inferActionProvider(action);
|
|
3340
|
+
}
|
|
3341
|
+
|
|
3342
|
+
function isEarnCatalogAction(action) {
|
|
3343
|
+
const actionKey = rowActionKey(action);
|
|
3344
|
+
return (
|
|
3345
|
+
actionKey.includes('_earn_') ||
|
|
3346
|
+
normalizeProviderId(action?.domain) === 'earn' ||
|
|
3347
|
+
normalizeProviderId(action?.category) === 'earn'
|
|
3348
|
+
);
|
|
3349
|
+
}
|
|
3350
|
+
|
|
3351
|
+
function isSpotTradingCatalogAction(action) {
|
|
3352
|
+
const actionKey = rowActionKey(action);
|
|
3353
|
+
return actionKey === 'swap' || actionKey === 'execute_optimal_swap' || actionKey === 'get_best_trading_quote';
|
|
3354
|
+
}
|
|
3355
|
+
|
|
3356
|
+
function isProviderActionKey(action, provider) {
|
|
3357
|
+
const actionKey = rowActionKey(action);
|
|
3358
|
+
const normalizedProvider = normalizeProviderId(provider).replace(/-/g, '_');
|
|
3359
|
+
if (!actionKey || !normalizedProvider) return false;
|
|
3360
|
+
return (
|
|
3361
|
+
actionKey === normalizedProvider ||
|
|
3362
|
+
actionKey.startsWith(`${normalizedProvider}_`) ||
|
|
3363
|
+
actionKey.includes(`_${normalizedProvider}_`) ||
|
|
3364
|
+
actionKey.endsWith(`_${normalizedProvider}`)
|
|
3365
|
+
);
|
|
3366
|
+
}
|
|
3367
|
+
|
|
3368
|
+
function actionMatchesProvider(action, requestedProvider, allActions) {
|
|
3369
|
+
const provider = getActionProviderWithInference(action);
|
|
3370
|
+
const actionKey = rowActionKey(action);
|
|
3371
|
+
if (provider === requestedProvider) return true;
|
|
3372
|
+
if (requestedProvider === 'trading') return isSpotTradingCatalogAction(action);
|
|
3373
|
+
// Here resolved metadata already disagrees with the filter; fall back to action-key shape only.
|
|
3374
|
+
if (requestedProvider === 'hyperliquid') return isProviderActionKey(action, 'hyperliquid');
|
|
3375
|
+
if (requestedProvider === 'polymarket') return isProviderActionKey(action, 'polymarket');
|
|
3376
|
+
if (requestedProvider === 'bridge') return isProviderActionKey(action, 'bridge');
|
|
3377
|
+
if (requestedProvider.startsWith('dogeos')) return isProviderActionKey(action, requestedProvider);
|
|
3378
|
+
if (requestedProvider === 'earn') {
|
|
3379
|
+
return provider === 'earn' || provider === 'morpho' || provider === 'curve' || isEarnCatalogAction(action);
|
|
3380
|
+
}
|
|
3381
|
+
if (requestedProvider === 'morpho' || requestedProvider === 'curve') {
|
|
3382
|
+
const hasProtocolSpecificEarnRows = allActions.some((candidate) => getActionProviderWithInference(candidate) === requestedProvider);
|
|
3383
|
+
return isProviderActionKey(action, requestedProvider) || (!hasProtocolSpecificEarnRows && isEarnCatalogAction(action));
|
|
3384
|
+
}
|
|
3385
|
+
if (requestedProvider === 'prediction') {
|
|
3386
|
+
return (
|
|
3387
|
+
provider === 'polymarket' ||
|
|
3388
|
+
provider === 'prediction' ||
|
|
3389
|
+
actionKey.includes('_prediction_') ||
|
|
3390
|
+
normalizeProviderId(action?.domain) === 'prediction' ||
|
|
3391
|
+
normalizeProviderId(action?.category) === 'prediction'
|
|
3392
|
+
);
|
|
3393
|
+
}
|
|
3394
|
+
return isProviderActionKey(action, requestedProvider);
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3231
3397
|
function applyActionFilters(actions, flags) {
|
|
3232
3398
|
let filtered = actions;
|
|
3233
3399
|
if (flags.catalog) {
|
|
@@ -3235,21 +3401,14 @@ function applyActionFilters(actions, flags) {
|
|
|
3235
3401
|
filtered = filtered.filter((a) => String(a.catalog || a.catalogId || 'default').trim().toLowerCase() === expectedCatalog);
|
|
3236
3402
|
}
|
|
3237
3403
|
if (flags.provider) {
|
|
3238
|
-
const expectedProvider =
|
|
3239
|
-
filtered = filtered.filter((a) =>
|
|
3240
|
-
const provider = getActionProvider(a);
|
|
3241
|
-
const actionKey = getActionKey(a).replace(/-/g, '_').toLowerCase();
|
|
3242
|
-
if (provider === expectedProvider) return true;
|
|
3243
|
-
if (expectedProvider === 'earn') return provider === 'morpho' || provider === 'curve' || actionKey.includes('_earn_');
|
|
3244
|
-
if (expectedProvider === 'prediction') return provider === 'polymarket' || actionKey.includes('_prediction_');
|
|
3245
|
-
return false;
|
|
3246
|
-
});
|
|
3404
|
+
const expectedProvider = normalizeProviderId(flags.provider);
|
|
3405
|
+
filtered = filtered.filter((a) => actionMatchesProvider(a, expectedProvider, filtered));
|
|
3247
3406
|
}
|
|
3248
3407
|
return filtered;
|
|
3249
3408
|
}
|
|
3250
3409
|
|
|
3251
3410
|
function getActionProvider(action) {
|
|
3252
|
-
return
|
|
3411
|
+
return normalizeProviderId(action?.provider || action?.providerId || action?.provider_id || action?.catalog || '');
|
|
3253
3412
|
}
|
|
3254
3413
|
|
|
3255
3414
|
async function resolveActionSelection(ctx, flags) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thirdfy/agent-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.27",
|
|
4
4
|
"description": "Thirdfy Agent CLI for onboarding, governance preflight, execute-intent, and status polling.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
"scripts": {
|
|
19
19
|
"test": "node --test \"test/**/*.test.cjs\"",
|
|
20
20
|
"lint": "node --check ./bin/thirdfy-agent.mjs",
|
|
21
|
+
"release:npm": "node ./scripts/release-npm.mjs",
|
|
22
|
+
"publish:npm:local": "bash ./scripts/local-npm-publish.sh",
|
|
21
23
|
"validate:public-docs": "node ./scripts/validate-public-docs.mjs",
|
|
22
24
|
"validate:cli-contract-schemas": "node ./scripts/validate-cli-contract-schemas.mjs",
|
|
23
25
|
"validate:actions": "node ./scripts/e2e/validate-actions.mjs",
|