@thirdfy/agent-cli 0.1.38 → 0.1.39

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,17 @@ All notable changes to `@thirdfy/agent-cli` are documented here. The format is b
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.39] - 2026-05-17
8
+
9
+ ### Added
10
+
11
+ - Framework guidance for Hermes, OpenClaw, and Claude Managed Agents in `help onboarding`, README, and command reference so agents can choose CLI/MCP rails correctly.
12
+ - Gator-style `delegation grant` alias and clearer external-wallet delegation next steps.
13
+
14
+ ### Changed
15
+
16
+ - Fresh solo profiles now default to `agent_wallet`, persist/resolve owner `userDid`, and use owner-matched mirror scope for hybrid validation.
17
+
7
18
  ## [0.1.38] - 2026-05-17
8
19
 
9
20
  ### Fixed
package/README.md CHANGED
@@ -9,12 +9,13 @@ Use it to:
9
9
  - run governance preflight checks
10
10
  - queue execute-intent requests with idempotency
11
11
  - poll intent status with stable JSON output for automation
12
- - choose execution topology with one switch: `thirdfy`, `self`, or `hybrid`
12
+ - choose execution topology with one switch: `agent_wallet`, `self`, `hybrid`, or `thirdfy`
13
13
  - configure profile-driven defaults (`personal`, `builder`, `network`)
14
14
 
15
15
  If you want the full developer docs, start here:
16
- - [Thirdfy Agent CLI docs](https://docs.thirdfy.com/api/thirdfy-agent-cli)
17
- - [API Reference home](https://docs.thirdfy.com/api)
16
+ - [Thirdfy Agent CLI hub](https://docs.thirdfy.com/documentation/agent-cli) (guided chapters)
17
+ - [Thirdfy Agent CLI — full reference](https://docs.thirdfy.com/documentation/api/thirdfy-agent-cli)
18
+ - [API Reference home](https://docs.thirdfy.com/documentation/api/api-reference)
18
19
  - [LLM docs map (llms.txt)](https://docs.thirdfy.com/llms.txt)
19
20
  - [LLM full API snapshot (llms-full.txt)](https://docs.thirdfy.com/llms-full.txt)
20
21
  - [Provider docs index (repo)](./docs/providers/index.md)
@@ -41,7 +42,7 @@ npx @thirdfy/agent-cli --help
41
42
 
42
43
  ## Release notes
43
44
 
44
- Version history and highlights: [CHANGELOG.md](./CHANGELOG.md). **v0.1.38** is a **documentation and metadata patch**: it republishes to npm so the package homepage matches the updated `README.md` on `main`, and aligns root `package-lock.json` version fields with `package.json`. **v0.1.37** adds **email OTP** `thirdfy-agent login email` (send code, then complete with `--code --accept-terms`), **`help onboarding`**, **`doctor auth`**, **`wallet list`**, and **masked `whoami`** output so agents and operators get first-run guidance without dumping secrets. **v0.1.35** extended `thirdfy-agent actions` hints for Polymarket Gamma-style discovery (`gamma_search_*` where catalog-backed) and legacy `search_polymarket` / `get_polymarket_*` reads, with public docs aligned to the deposit-wallet (pUSD / POLY_1271) operator path. Earlier releases added provider discovery parity, portfolio analytics, managed-wallet swap normalization, and **self/build-tx** swap human-decimal `amountIn` parity when using `amountInHuman` + `tokenInDecimals`.
45
+ Version history and highlights: [CHANGELOG.md](./CHANGELOG.md). **v0.1.39** makes `agent_wallet` the fresh solo default, adds framework guidance for Hermes/OpenClaw/Claude Managed Agents, clarifies Gator/ERC-7710 delegation flows, and keeps BYOW/self plus hybrid/thirdfy mode switching explicit. **v0.1.38** is a **documentation and metadata patch**: it republishes to npm so the package homepage matches the updated `README.md` on `main`, and aligns root `package-lock.json` version fields with `package.json`. **v0.1.37** adds **email OTP** `thirdfy-agent login email` (send code, then complete with `--code --accept-terms`), **`help onboarding`**, **`doctor auth`**, **`wallet list`**, and **masked `whoami`** output so agents and operators get first-run guidance without dumping secrets. Earlier releases added provider discovery parity, portfolio analytics, managed-wallet swap normalization, and **self/build-tx** swap human-decimal `amountIn` parity when using `amountInHuman` + `tokenInDecimals`.
45
46
 
46
47
  **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.
47
48
 
@@ -103,7 +104,7 @@ thirdfy-agent logout --json
103
104
  thirdfy-agent logout --all --json
104
105
  ```
105
106
 
106
- `login email` is a two-step headless-safe flow. Without `--code`, the CLI asks the Thirdfy API onboarding broker to send a Privy email OTP and exits with the exact next command. With `--code --accept-terms`, it stores a short-lived owner session in `~/.thirdfy/config.json`, records linked EVM/Solana wallets when Privy returns them, and stores a new agent API key when first-run bootstrap issues one. Use `--not-interactive` / `--ni` in automation so missing input fails fast instead of prompting — place **`--ni` after the `login email` subcommand** (for example `thirdfy-agent login email you@example.com --code … --accept-terms --ni`); a leading `thirdfy-agent --ni login email …` is parsed incorrectly because `--ni` would consume the `login` token as its value.
107
+ `login email` is a two-step headless-safe flow. Without `--code`, the CLI asks the Thirdfy API onboarding broker to send a Privy email OTP and exits with the exact next command. With `--code --accept-terms`, it stores a short-lived owner session in `~/.thirdfy/config.json`, records linked EVM/Solana wallets plus the owner `userDid` when Privy returns them, stores a new agent API key when first-run bootstrap issues one, and defaults new solo profiles to `agent_wallet`. Use `--not-interactive` / `--ni` in automation so missing input fails fast instead of prompting — place **`--ni` after the `login email` subcommand** (for example `thirdfy-agent login email you@example.com --code … --accept-terms --ni`); a leading `thirdfy-agent --ni login email …` is parsed incorrectly because `--ni` would consume the `login` token as its value.
107
108
 
108
109
  `logout --all` is provider-agnostic: it attempts owner-session revocation when a session token exists, then always clears local credentials.
109
110
 
@@ -149,15 +150,17 @@ thirdfy-agent bootstrap complete --agent-key "0xYOUR_AGENT_KEY" --challenge-id "
149
150
 
150
151
  `thirdfy-agent` supports one command surface with four run modes:
151
152
 
152
- - `--run-mode thirdfy` -> Thirdfy-governed execute-intent rail (default for `profile=network`)
153
- - `--run-mode self` -> self-custody rail (`build-tx` flow; default for `profile=personal`)
153
+ - `--run-mode agent_wallet` -> managed solo wallet execution rail and fresh email-login default
154
+ - `--run-mode self` -> self-custody rail (`build-tx` flow)
154
155
  - `--run-mode hybrid` -> self-custody + governance mirror metadata (default for `profile=builder`)
155
- - `--run-mode agent_wallet` -> managed wallet execution rail for Claude-friendly hosted execution
156
+ - `--run-mode thirdfy` -> Thirdfy-governed execute-intent rail (default for `profile=network`)
156
157
 
157
158
  | Goal | Recommended mode | Why |
158
159
  | --- | --- | --- |
160
+ | Fast solo managed-wallet trading | `agent_wallet` | Uses `/execution-wallet` + `/execute`; owner `userDid` comes from login config. |
159
161
  | BYOW signing and local custody | `self` | Keeps signing and broadcast on your wallet path. |
160
- | Managed delegated execution | `thirdfy` | Uses delegated governance rail for hosted execution. |
162
+ | External wallet delegated execution | `hybrid` or `thirdfy` after `delegation create/activate` | Uses Gator/ERC-7710 authority from the user wallet to the Thirdfy/session executor. |
163
+ | Publisher fan-out / subscriber execution | `thirdfy` | Uses delegated governance rail and active `delegation_bindings`. |
161
164
  | Self execution plus governance mirror checks | `hybrid` | Preserves local execution while emitting managed-lane mirrors. |
162
165
  | Managed wallet primary + governance mirror checks | `hybrid --hybrid-wallet-mode agent_wallet` | Uses managed wallet as primary hybrid path while still running Thirdfy mirror checks. |
163
166
 
@@ -166,7 +169,7 @@ Auth expectations by mode:
166
169
  - `self`: requires execution identity (`agentApiKey`) today; keyless self lane is blocked with deterministic `SELF_OPEN_DISABLED`.
167
170
  - `hybrid`: requires execution identity and governed mirror semantics (`--hybrid-wallet-mode self|agent_wallet`, default `self`).
168
171
  - `thirdfy`: requires execution identity and delegated governance path.
169
- - `agent_wallet`: requires execution identity and delegated managed-wallet path.
172
+ - `agent_wallet`: requires execution identity and owner `userDid`, but does not require subscriber delegation when the owner identity matches the agent wallet/creator.
170
173
  - custody mode defaults are profile-aware:
171
174
  - `managed` default for `thirdfy`
172
175
  - `external` default for `self` and `hybrid`
@@ -177,7 +180,7 @@ Selection precedence:
177
180
  1. `--run-mode`
178
181
  2. `THIRDFY_RUN_MODE`
179
182
  3. saved profile config (`~/.thirdfy/config.json`)
180
- 4. profile default
183
+ 4. profile default (`personal=agent_wallet`, `builder=hybrid`, `network=thirdfy`)
181
184
 
182
185
  Profile commands:
183
186
 
@@ -189,6 +192,16 @@ thirdfy-agent whoami --json
189
192
 
190
193
  `profile use --profile <name>` resets run mode to that profile default unless `--run-mode` is explicitly provided.
191
194
 
195
+ ## Framework Guidance
196
+
197
+ Use the same execution identities across frameworks, but choose the rail by who signs and who the agent acts for:
198
+
199
+ - **Hermes agents:** provision the Thirdfy profile and env before the Hermes dashboard/runtime starts, run `thirdfy-agent doctor auth` and `doctor self` during startup checks, prefer `agent_wallet` for the agent’s own managed wallet, and keep `thirdfy` for publisher/fanout or delegated external-wallet execution.
200
+ - **OpenClaw agents:** store Thirdfy credentials as runtime secrets, call `thirdfy-agent actions --provider <id>` before planning, use `run --run-mode agent_wallet` for own-wallet actions, use `self` only when OWS/local signing is configured, and switch to `hybrid`/`thirdfy` only after delegation readiness is confirmed.
201
+ - **Claude Managed Agents:** prefer MCP `agentRun` / `walletExecute` for solo managed execution, `buildTx` / `walletSign` for BYOW local signing, and `executeIntent` only for subscriber fanout or explicit validation-only mirror previews. The CLI remains useful for smoke checks and local operator recovery.
202
+
203
+ For all frameworks, treat `agentApiKey` as a hidden execution credential in secret storage, keep owner-session tokens short lived, and verify mode requirements with `thirdfy-agent help onboarding --json`.
204
+
192
205
  ### One-command self execution (BYOW)
193
206
 
194
207
  Use `--broadcast` with `run --run-mode self` to keep one deterministic command for build/sign/send:
@@ -400,7 +413,7 @@ Managed-self execution performs strict wallet preflight and returns deterministi
400
413
  ## More docs
401
414
 
402
415
  - OpenClaw CLI onboarding flow:
403
- [docs.thirdfy.com/api/thirdfy-agent-cli#create-an-openclaw-agent-with-the-cli](https://docs.thirdfy.com/api/thirdfy-agent-cli#create-an-openclaw-agent-with-the-cli)
416
+ [docs.thirdfy.com/documentation/api/thirdfy-agent-cli#create-an-openclaw-agent-with-the-cli](https://docs.thirdfy.com/documentation/api/thirdfy-agent-cli#create-an-openclaw-agent-with-the-cli)
404
417
  - Creator platform (agent registration and keys):
405
418
  [thirdfy.com/creator](https://thirdfy.com/creator)
406
419
 
@@ -416,7 +429,7 @@ npm run e2e:managed:delegation:parity
416
429
 
417
430
  ## Release
418
431
 
419
- Version history and user-facing notes: [CHANGELOG.md](./CHANGELOG.md) (for example [v0.1.38](https://github.com/thirdfy/agent-cli/releases/tag/v0.1.38) — npm README + lockfile metadata alignment; [v0.1.37](https://github.com/thirdfy/agent-cli/releases/tag/v0.1.37) — email OTP login, onboarding help, auth doctor, wallet list, masked `whoami`). **Before every version bump or npm publish:** update this **README** (release notes paragraph, quick start, and command groups) so the npm package page matches what ships; keep `CHANGELOG.md`, [command reference](./docs/command-reference.md), and MCP summaries aligned when discovery or onboarding surfaces change.
432
+ Version history and user-facing notes: [CHANGELOG.md](./CHANGELOG.md) (for example [v0.1.39](https://github.com/thirdfy/agent-cli/releases/tag/v0.1.39) — agent-wallet solo default, framework guidance, and delegation UX; [v0.1.38](https://github.com/thirdfy/agent-cli/releases/tag/v0.1.38) — npm README + lockfile metadata alignment; [v0.1.37](https://github.com/thirdfy/agent-cli/releases/tag/v0.1.37) — email OTP login, onboarding help, auth doctor, wallet list, masked `whoami`). **Before every version bump or npm publish:** update this **README** (release notes paragraph, quick start, and command groups) so the npm package page matches what ships; keep `CHANGELOG.md`, [command reference](./docs/command-reference.md), and MCP summaries aligned when discovery or onboarding surfaces change.
420
433
 
421
434
  ```bash
422
435
  npm version patch
@@ -43,7 +43,7 @@ const CUSTODY_MODES = ['managed', 'external'];
43
43
  const EFFECT_CHECK_MODES = ['strict', 'relaxed', 'off'];
44
44
  let negotiatedCapabilitiesCache = null;
45
45
  const PROFILE_DEFAULTS = {
46
- personal: 'self',
46
+ personal: 'agent_wallet',
47
47
  builder: 'hybrid',
48
48
  network: 'thirdfy',
49
49
  };
@@ -224,6 +224,7 @@ async function main() {
224
224
  await commandTrackAction(context, subFlags, capabilities);
225
225
  return;
226
226
  case 'delegation create':
227
+ case 'delegation grant':
227
228
  await commandDelegationCreate(context, subFlags, capabilities);
228
229
  return;
229
230
  case 'delegation init-custodial':
@@ -1432,7 +1433,17 @@ async function commandDelegationCreate(ctx, flags, capabilities) {
1432
1433
  success,
1433
1434
  code: success ? 'DELEGATION_CREATED' : 'DELEGATION_CREATE_FAILED',
1434
1435
  message: response?.message || (success ? 'Delegation payload created' : 'Delegation create failed'),
1435
- data: response,
1436
+ data: {
1437
+ ...response,
1438
+ delegationModel: 'gator_erc7710',
1439
+ nextSteps: success
1440
+ ? [
1441
+ 'Sign data.delegation with the external wallet or OWS account that owns --owner-address.',
1442
+ 'Run `thirdfy-agent delegation activate --agent-key <key> --wallet-address <owner> --session-account-address <delegate> --delegation-manager <manager> --delegation <json> --signature <hex>`.',
1443
+ 'Verify with `thirdfy-agent delegation inspect --agent-key <key> --verify`, then use `delegation redeem` or run with --run-mode hybrid|thirdfy for delegated execution.',
1444
+ ]
1445
+ : [],
1446
+ },
1436
1447
  meta: {
1437
1448
  apiBase: ctx.apiBase,
1438
1449
  capabilitiesVersion: capabilities?.contractVersion || null,
@@ -1533,7 +1544,16 @@ async function commandDelegationActivate(ctx, flags, capabilities) {
1533
1544
  success,
1534
1545
  code: success ? 'DELEGATION_ACTIVATED' : 'DELEGATION_ACTIVATE_FAILED',
1535
1546
  message: response?.message || (success ? 'Delegation activated' : 'Delegation activate failed'),
1536
- data: response,
1547
+ data: {
1548
+ ...response,
1549
+ delegationModel: 'gator_erc7710',
1550
+ nextSteps: success
1551
+ ? [
1552
+ 'Run `thirdfy-agent delegation inspect --agent-key <key> --verify` to confirm period allowance and revocation state.',
1553
+ 'Use `thirdfy-agent delegation redeem --run-mode hybrid|thirdfy ...` when Thirdfy/session executor should act under this external-wallet delegation.',
1554
+ ]
1555
+ : [],
1556
+ },
1537
1557
  meta: {
1538
1558
  apiBase: ctx.apiBase,
1539
1559
  capabilitiesVersion: capabilities?.contractVersion || null,
@@ -2434,8 +2454,8 @@ async function commandProfileShow(ctx, _flags) {
2434
2454
  message: 'Profile configuration loaded',
2435
2455
  data: {
2436
2456
  profile: ctx.profile || config.profile || 'personal',
2437
- runMode: ctx.runMode || config.runMode || 'thirdfy',
2438
- custodyMode: ctx.custodyMode || config.custodyMode || defaultCustodyModeForRunMode(ctx.runMode || config.runMode || 'thirdfy'),
2457
+ runMode: ctx.runMode || config.runMode || 'agent_wallet',
2458
+ custodyMode: ctx.custodyMode || config.custodyMode || defaultCustodyModeForRunMode(ctx.runMode || config.runMode || 'agent_wallet'),
2439
2459
  profileDefaults: PROFILE_DEFAULTS,
2440
2460
  configPath: getProfileConfigPath(),
2441
2461
  config,
@@ -2455,7 +2475,7 @@ function maskSecret(value) {
2455
2475
  function buildOnboardingHelp(ctx) {
2456
2476
  return {
2457
2477
  title: 'Thirdfy Agent CLI onboarding',
2458
- summary: 'Use email OTP, wallet-sign, or existing credentials to create owner auth, wallets, and agent execution credentials.',
2478
+ summary: 'Use email OTP, wallet-sign, or existing credentials to create owner auth, wallets, and hidden agent execution credentials. Fresh solo profiles default to agent_wallet.',
2459
2479
  paths: [
2460
2480
  {
2461
2481
  id: 'email_otp',
@@ -2466,6 +2486,7 @@ function buildOnboardingHelp(ctx) {
2466
2486
  'thirdfy-agent login email user@example.com --code <otp> --accept-terms --key-name "My Agent"',
2467
2487
  'thirdfy-agent whoami',
2468
2488
  'thirdfy-agent managed wallet init --chain-id 8453',
2489
+ 'thirdfy-agent preflight --run-mode agent_wallet --action <action> --params <json> --json',
2469
2490
  ],
2470
2491
  },
2471
2492
  {
@@ -2499,6 +2520,21 @@ function buildOnboardingHelp(ctx) {
2499
2520
  'thirdfy-agent login email user@example.com --code 123456 --accept-terms --ni (place --ni after the subcommand so it is not parsed as a flag value)',
2500
2521
  rule: 'Commands must fail fast instead of waiting for prompts when required input is missing.',
2501
2522
  },
2523
+ executionModes: {
2524
+ agent_wallet: 'Solo managed wallet execution through /execution-wallet + /execute; no subscriber binding when owner userDid matches.',
2525
+ self: 'BYOW/OWS local signing through build-tx, wallet sign, and wallet submit.',
2526
+ hybrid: 'Primary self or agent_wallet execution with optional Thirdfy mirror validation.',
2527
+ thirdfy: 'Publisher/fanout execute-intent; requires active subscriber/delegation bindings for writes.',
2528
+ externalDelegation: 'Use delegation create/grant -> sign -> activate -> inspect/balance -> redeem for Gator/ERC-7710 external-wallet authority.',
2529
+ },
2530
+ frameworkGuidance: {
2531
+ hermes:
2532
+ 'Hermes agents should receive a pre-provisioned Thirdfy profile/env, run doctor auth/self at startup, use agent_wallet for managed solo writes, and keep strategy logic separate from CLI secrets.',
2533
+ openclaw:
2534
+ 'OpenClaw agents should keep Thirdfy credentials in runtime secrets, use actions discovery before planning, prefer run --run-mode agent_wallet for own-wallet execution, and use thirdfy only for publisher/fanout.',
2535
+ claudeManagedAgents:
2536
+ 'Claude Managed Agents should use MCP agentRun/walletExecute for solo managed execution, walletSign/buildTx for BYOW, and executeIntent only for fanout or mirror previews.',
2537
+ },
2502
2538
  apiBase: ctx.apiBase,
2503
2539
  };
2504
2540
  }
@@ -2518,14 +2554,15 @@ async function commandWhoami(ctx, _flags) {
2518
2554
  const auth = config.auth && typeof config.auth === 'object' ? config.auth : {};
2519
2555
  const agent = config.agent && typeof config.agent === 'object' ? config.agent : {};
2520
2556
  const wallets = config.wallets && typeof config.wallets === 'object' ? config.wallets : {};
2557
+ const runMode = ctx.runMode || config.runMode || 'agent_wallet';
2521
2558
  printEnvelope({
2522
2559
  success: true,
2523
2560
  code: 'WHOAMI_OK',
2524
2561
  message: 'Thirdfy CLI identity loaded',
2525
2562
  data: {
2526
2563
  profile: ctx.profile || config.profile || 'personal',
2527
- runMode: ctx.runMode || config.runMode || 'thirdfy',
2528
- custodyMode: ctx.custodyMode || config.custodyMode || defaultCustodyModeForRunMode(ctx.runMode || config.runMode || 'thirdfy'),
2564
+ runMode,
2565
+ custodyMode: ctx.custodyMode || config.custodyMode || defaultCustodyModeForRunMode(runMode),
2529
2566
  auth: {
2530
2567
  source: auth.source || null,
2531
2568
  hasAuthToken: Boolean(auth.authToken),
@@ -2539,6 +2576,7 @@ async function commandWhoami(ctx, _flags) {
2539
2576
  agentKey: agent.agentKey || null,
2540
2577
  },
2541
2578
  wallets: {
2579
+ userDid: wallets.userDid || config.identity?.userDid || null,
2542
2580
  primaryEvmWallet: wallets.primaryEvmWallet || null,
2543
2581
  evm: Array.isArray(wallets.evm) ? wallets.evm : [],
2544
2582
  solana: Array.isArray(wallets.solana) ? wallets.solana : [],
@@ -2571,6 +2609,8 @@ async function commandDoctorAuth(ctx, _flags) {
2571
2609
  const config = loadProfileConfig();
2572
2610
  const auth = config.auth && typeof config.auth === 'object' ? config.auth : {};
2573
2611
  const agent = config.agent && typeof config.agent === 'object' ? config.agent : {};
2612
+ const runMode = normalizeRunMode(ctx.runMode || config.runMode || 'agent_wallet');
2613
+ const userDid = resolveEffectiveUserDid({});
2574
2614
  const ownerSessionTokenFromEnv = String(process.env.THIRDFY_OWNER_SESSION_TOKEN || '').trim();
2575
2615
  const authTokenFromEnv = String(process.env.THIRDFY_AUTH_TOKEN || '').trim();
2576
2616
  const agentApiKeyFromEnv = String(process.env.THIRDFY_AGENT_API_KEY || '').trim();
@@ -2598,6 +2638,14 @@ async function commandDoctorAuth(ctx, _flags) {
2598
2638
  ? 'agent API key from THIRDFY_AGENT_API_KEY'
2599
2639
  : 'not stored yet (optional until execution); complete onboarding or bootstrap to add one',
2600
2640
  },
2641
+ {
2642
+ name: 'user-did',
2643
+ optional: runMode !== 'agent_wallet',
2644
+ ok: Boolean(userDid),
2645
+ detail: userDid
2646
+ ? `user DID available (${userDid})`
2647
+ : 'missing user DID; run `thirdfy-agent login email <email>` or set THIRDFY_USER_DID',
2648
+ },
2601
2649
  {
2602
2650
  name: 'wallet-profile',
2603
2651
  ok: Boolean(config.wallets?.primaryEvmWallet || (Array.isArray(config.wallets?.evm) && config.wallets.evm.length)),
@@ -2660,7 +2708,7 @@ async function commandLogin(ctx, flags) {
2660
2708
  const current = loadProfileConfig();
2661
2709
  const authToken = String(flags.authToken || process.env.THIRDFY_AUTH_TOKEN || '').trim();
2662
2710
  let ownerSessionToken = String(flags.ownerSessionToken || process.env.THIRDFY_OWNER_SESSION_TOKEN || '').trim();
2663
- const loginRunMode = normalizeRunMode(flags.runMode || current.runMode || process.env.THIRDFY_RUN_MODE || 'thirdfy');
2711
+ const loginRunMode = normalizeRunMode(flags.runMode || current.runMode || process.env.THIRDFY_RUN_MODE || 'agent_wallet');
2664
2712
  const custodyMode = normalizeCustodyMode(
2665
2713
  flags.custodyMode || current.custodyMode || process.env.THIRDFY_CUSTODY_MODE,
2666
2714
  loginRunMode
@@ -2842,10 +2890,10 @@ async function commandLoginEmail(ctx, flags) {
2842
2890
  acceptTerms: true,
2843
2891
  keyName,
2844
2892
  agentKey: String(flags.agentKey || '').trim() || undefined,
2845
- runMode: normalizeRunMode(flags.runMode || current.runMode || process.env.THIRDFY_RUN_MODE || 'thirdfy'),
2893
+ runMode: normalizeRunMode(flags.runMode || current.runMode || process.env.THIRDFY_RUN_MODE || 'agent_wallet'),
2846
2894
  custodyMode: normalizeCustodyMode(
2847
2895
  flags.custodyMode || current.custodyMode || process.env.THIRDFY_CUSTODY_MODE,
2848
- normalizeRunMode(flags.runMode || current.runMode || process.env.THIRDFY_RUN_MODE || 'thirdfy')
2896
+ normalizeRunMode(flags.runMode || current.runMode || process.env.THIRDFY_RUN_MODE || 'agent_wallet')
2849
2897
  ),
2850
2898
  bootstrapAgent: !parseBooleanFlag(flags.noBootstrapAgent, false),
2851
2899
  rotateAgentKey: parseBooleanFlag(flags.rotateAgentKey, false),
@@ -2856,12 +2904,14 @@ async function commandLoginEmail(ctx, flags) {
2856
2904
  const agentApiKey = String(bootstrap.agentApiKey || '').trim();
2857
2905
  const agentKey = String(bootstrap.agentKey || data.owner?.creatorWallet || '').trim();
2858
2906
  const wallets = data.wallets && typeof data.wallets === 'object' ? data.wallets : {};
2907
+ const userDid = String(data.owner?.creatorDid || wallets.userDid || '').trim();
2859
2908
  const primaryEvmWallet = String(wallets.primaryEvmWallet || data.owner?.creatorWallet || '').trim();
2860
2909
  const persistedWallets = {
2861
2910
  ...wallets,
2911
+ ...(userDid ? { userDid } : {}),
2862
2912
  ...(primaryEvmWallet ? { primaryEvmWallet } : {}),
2863
2913
  };
2864
- const runMode = normalizeRunMode(flags.runMode || current.runMode || process.env.THIRDFY_RUN_MODE || 'thirdfy');
2914
+ const runMode = normalizeRunMode(flags.runMode || current.runMode || process.env.THIRDFY_RUN_MODE || 'agent_wallet');
2865
2915
  const custodyMode = normalizeCustodyMode(flags.custodyMode || current.custodyMode || process.env.THIRDFY_CUSTODY_MODE, runMode);
2866
2916
  if (!ownerSessionToken) {
2867
2917
  throw createCliError('LOGIN_EMAIL_OWNER_SESSION_MISSING', 'Email onboarding completed without an owner session token.');
@@ -3590,6 +3640,15 @@ function buildBuildTxPayload(flags, resolvedAction) {
3590
3640
  return payload;
3591
3641
  }
3592
3642
 
3643
+ function resolveEffectiveUserDid(flags) {
3644
+ const explicit = String(flags.userDid || '').trim();
3645
+ if (explicit) return explicit;
3646
+ const envUserDid = String(process.env.THIRDFY_USER_DID || '').trim();
3647
+ if (envUserDid) return envUserDid;
3648
+ const config = loadProfileConfig();
3649
+ return String(config?.wallets?.userDid || config?.identity?.userDid || '').trim();
3650
+ }
3651
+
3593
3652
  function buildManagedExecutePayload(flags, options) {
3594
3653
  const runMode = String(options.runMode || flags.runMode || 'agent_wallet').trim().toLowerCase();
3595
3654
  const params = getPreparedParams(flags);
@@ -3620,7 +3679,7 @@ function buildManagedExecutePayload(flags, options) {
3620
3679
  const payload = {
3621
3680
  agentApiKey: resolveAgentApiKey(flags, runMode),
3622
3681
  action: String(options.resolvedAction || requireFlag(flags, 'action', 'Missing --action')).trim(),
3623
- userDid: String(flags.userDid || process.env.THIRDFY_USER_DID || '').trim(),
3682
+ userDid: resolveEffectiveUserDid(flags),
3624
3683
  params: managedParams,
3625
3684
  chainId: Number(flags.chainId || 8453),
3626
3685
  executionStrategy: {
@@ -3631,7 +3690,7 @@ function buildManagedExecutePayload(flags, options) {
3631
3690
  if (!payload.userDid) {
3632
3691
  throw createCliError(
3633
3692
  'MISSING_USER_DID',
3634
- 'Managed wallet execution requires --user-did (or THIRDFY_USER_DID).'
3693
+ 'Managed wallet execution requires --user-did, THIRDFY_USER_DID, or a saved userDid from `thirdfy-agent login email`.'
3635
3694
  );
3636
3695
  }
3637
3696
  if (flags.estimatedAmountUsd) payload.estimatedAmountUsd = Number(flags.estimatedAmountUsd);
@@ -3655,13 +3714,13 @@ async function resolveManagedExecutionPreflight(ctx, flags, resolved, options =
3655
3714
  const chainId = Number(flags.chainId || 8453);
3656
3715
  const runMode = String(options.runMode || 'agent_wallet').trim().toLowerCase();
3657
3716
  const agentApiKey = resolveAgentApiKey(flags, runMode);
3658
- const userDid = String(flags.userDid || process.env.THIRDFY_USER_DID || '').trim();
3717
+ const userDid = resolveEffectiveUserDid(flags);
3659
3718
  if (!userDid) {
3660
3719
  return {
3661
3720
  success: false,
3662
3721
  blockedReason: 'MISSING_USER_DID',
3663
3722
  blockedStage: 'routing',
3664
- error: 'Managed wallet execution requires --user-did (or THIRDFY_USER_DID).',
3723
+ error: 'Managed wallet execution requires --user-did, THIRDFY_USER_DID, or a saved userDid from `thirdfy-agent login email`.',
3665
3724
  signerMethod: 'managed_wallet_server',
3666
3725
  };
3667
3726
  }
@@ -3742,8 +3801,16 @@ function buildIntentPayload(flags, options) {
3742
3801
  if (flags.catalog) payload.catalog = String(flags.catalog).trim();
3743
3802
  if (flags.chainId) payload.chainId = Number(flags.chainId);
3744
3803
  if (flags.estimatedAmountUsd) payload.estimatedAmountUsd = Number(flags.estimatedAmountUsd);
3745
- if (flags.userDid) payload.userDid = String(flags.userDid);
3804
+ const userDid = resolveEffectiveUserDid(flags);
3805
+ if (flags.userDid || (options.validationOnly && (runMode === 'agent_wallet' || (runMode === 'hybrid' && options.mirrorOnly)))) {
3806
+ if (userDid) payload.userDid = userDid;
3807
+ }
3746
3808
  if (options.validationOnly) payload.executionLane = 'validation_only';
3809
+ if (flags.executionScope) {
3810
+ payload.executionScope = String(flags.executionScope).trim();
3811
+ } else if (options.validationOnly && (runMode === 'agent_wallet' || (runMode === 'hybrid' && options.mirrorOnly))) {
3812
+ payload.executionScope = 'solo_owner_mirror';
3813
+ }
3747
3814
  if (options.runMode) {
3748
3815
  payload.executionStrategy = {
3749
3816
  runMode: String(options.runMode),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdfy/agent-cli",
3
- "version": "0.1.38",
3
+ "version": "0.1.39",
4
4
  "description": "Thirdfy Agent CLI for onboarding, governance preflight, execute-intent, and status polling.",
5
5
  "type": "module",
6
6
  "bin": {