@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 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` (publish after merge)
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 earn/prediction provider discovery, case-insensitive `actions --provider` filtering, self-lane guards for offchain venue orders, and npm-facing README refresh (**v0.1.24**).
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
 
@@ -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 = String(flags.provider).trim().toLowerCase();
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 String(action?.provider || action?.providerId || action?.provider_id || action?.catalog || '').trim().toLowerCase();
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.25",
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",