@thirdfy/agent-cli 0.1.8 → 0.1.9

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,10 @@ All notable changes to `@thirdfy/agent-cli` are documented here. The format is b
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ### Fixed
8
+
9
+ - **Self preflight routing for swap-like actions:** `preflight --run-mode self` now selects the validation route by action capability. When an action advertises `supportsExecuteIntent=false` and `supportsBuildTx=true`, preflight uses `build-tx` directly instead of forcing execute-intent validation.
10
+
7
11
  ## [0.1.8] - 2026-04-07
8
12
 
9
13
  **npm:** [`@thirdfy/agent-cli@0.1.8`](https://www.npmjs.com/package/@thirdfy/agent-cli/v/0.1.8)
package/README.md CHANGED
@@ -33,6 +33,13 @@ Run without global install:
33
33
  npx @thirdfy/agent-cli --help
34
34
  ```
35
35
 
36
+ ## What's new in 0.1.8
37
+
38
+ - Managed custodial lifecycle parity validation is now first-class in CLI E2E/certification.
39
+ - `doctor self` runs as a local diagnostic command without capabilities negotiation.
40
+ - Self-exec effect-check fallback payloads are hardened for deterministic automation parsing.
41
+ - Managed wallet aliases (`managed wallet init/grant`) are wired directly to custodial delegation handlers.
42
+
36
43
  ## Quick start
37
44
 
38
45
  ```bash
@@ -101,6 +108,9 @@ thirdfy-agent agent register --owner-session-token "$THIRDFY_OWNER_SESSION_TOKEN
101
108
  - `run` auto-generates `idempotencyKey` by default when not provided.
102
109
  - For deterministic retries across workers/restarts, pass your own stable `--idempotency-key`.
103
110
  - `preflight` does not force idempotency keys.
111
+ - `preflight --run-mode self` is capability-aware:
112
+ - if an action supports execute-intent validation, CLI uses `executionLane=validation_only` before building tx;
113
+ - if an action advertises `supportsExecuteIntent=false` and `supportsBuildTx=true`, CLI routes preflight directly to `build-tx`.
104
114
 
105
115
  ## Run modes and profiles
106
116
 
@@ -110,6 +120,12 @@ thirdfy-agent agent register --owner-session-token "$THIRDFY_OWNER_SESSION_TOKEN
110
120
  - `--run-mode self` -> self-custody rail (`build-tx` flow; default for `profile=personal`)
111
121
  - `--run-mode hybrid` -> self-custody + governance mirror metadata (default for `profile=builder`)
112
122
 
123
+ | Goal | Recommended mode | Why |
124
+ | --- | --- | --- |
125
+ | BYOW signing and local custody | `self` | Keeps signing and broadcast on your wallet path. |
126
+ | Managed delegated execution | `thirdfy` | Uses delegated governance rail for hosted execution. |
127
+ | Self execution plus governance mirror checks | `hybrid` | Preserves local execution while emitting managed-lane mirrors. |
128
+
113
129
  Auth expectations by mode:
114
130
 
115
131
  - `self`: requires execution identity (`agentApiKey`) today; keyless self lane is blocked with deterministic `SELF_OPEN_DISABLED`.
@@ -517,7 +517,7 @@ async function commandPreflight(ctx, flags, capabilities) {
517
517
  prepareActionParamsForFlags(flags, resolved.resolvedAction);
518
518
  const runMode = getEffectiveRunMode(ctx, flags);
519
519
  enforceChainCompatibility(capabilities, flags, runMode);
520
- const backendResult = await runPreflightByMode(runMode, ctx, flags, resolved.resolvedAction);
520
+ const backendResult = await runPreflightByMode(runMode, ctx, flags, resolved);
521
521
  const normalized = backendResult.normalized;
522
522
  printEnvelope({
523
523
  success: normalized.success,
@@ -529,6 +529,7 @@ async function commandPreflight(ctx, flags, capabilities) {
529
529
  catalog: flags.catalog || null,
530
530
  requestedAction: resolved.requestedAction,
531
531
  resolvedAction: resolved.resolvedAction,
532
+ preflightRoute: backendResult.route,
532
533
  runMode,
533
534
  profile: ctx.profile || null,
534
535
  swapInput: flags.__swapInput || null,
@@ -1710,13 +1711,22 @@ function enforceChainCompatibility(capabilities, flags, runMode) {
1710
1711
  }
1711
1712
  }
1712
1713
 
1713
- async function runPreflightByMode(runMode, ctx, flags, resolvedAction) {
1714
+ function shouldUseBuildTxPreflight(runMode, resolved) {
1715
+ if (runMode !== 'self') return false;
1716
+ const meta = resolved?.resolvedActionMeta || null;
1717
+ if (!meta || typeof meta !== 'object') return false;
1718
+ return meta.supportsExecuteIntent === false && meta.supportsBuildTx === true;
1719
+ }
1720
+
1721
+ async function runPreflightByMode(runMode, ctx, flags, resolved) {
1722
+ const resolvedAction = resolved.resolvedAction;
1714
1723
  if (runMode === 'self') {
1724
+ const route = shouldUseBuildTxPreflight(runMode, resolved) ? 'build_tx' : 'execute_intent_validation';
1715
1725
  const normalized = await executeSelfRun(
1716
1726
  ctx,
1717
1727
  flags,
1718
1728
  { resolvedAction },
1719
- { skipPreflight: false }
1729
+ { skipPreflight: route === 'build_tx' }
1720
1730
  );
1721
1731
  const blockedByGovernance = !normalized.success && Boolean(normalized.preflightBlocked);
1722
1732
  return {
@@ -1725,6 +1735,7 @@ async function runPreflightByMode(runMode, ctx, flags, resolvedAction) {
1725
1735
  : normalized.success
1726
1736
  ? 'Self preflight completed (unsigned transaction ready)'
1727
1737
  : 'Self preflight failed',
1738
+ route,
1728
1739
  normalized,
1729
1740
  };
1730
1741
  }
@@ -1745,6 +1756,7 @@ async function runPreflightByMode(runMode, ctx, flags, resolvedAction) {
1745
1756
  : runMode === 'hybrid'
1746
1757
  ? 'Hybrid mirror preflight failed'
1747
1758
  : 'Preflight failed',
1759
+ route: 'execute_intent_validation',
1748
1760
  normalized,
1749
1761
  };
1750
1762
  }
@@ -2006,18 +2018,19 @@ async function resolveActionSelection(ctx, flags) {
2006
2018
  .map((action) => ({
2007
2019
  key: getActionKey(action),
2008
2020
  aliases: getActionAliases(action),
2021
+ action,
2009
2022
  }))
2010
2023
  .filter((entry) => entry.key);
2011
2024
 
2012
2025
  if (!keyed.length) {
2013
- return { requestedAction, resolvedAction: requestedAction };
2026
+ return { requestedAction, resolvedAction: requestedAction, resolvedActionMeta: null };
2014
2027
  }
2015
2028
 
2016
2029
  // Prefer direct action id matches over alias matches.
2017
2030
  // This keeps UX simple for commands like `--action swap` when another action aliases to "swap".
2018
2031
  const exactKey = keyed.filter((entry) => entry.key.toLowerCase() === requestedLower);
2019
2032
  if (exactKey.length === 1) {
2020
- return { requestedAction, resolvedAction: exactKey[0].key };
2033
+ return { requestedAction, resolvedAction: exactKey[0].key, resolvedActionMeta: exactKey[0].action || null };
2021
2034
  }
2022
2035
  if (exactKey.length > 1) {
2023
2036
  throw new Error(
@@ -2029,7 +2042,7 @@ async function resolveActionSelection(ctx, flags) {
2029
2042
 
2030
2043
  const exactAlias = keyed.filter((entry) => entry.aliases.some((a) => a.toLowerCase() === requestedLower));
2031
2044
  if (exactAlias.length === 1) {
2032
- return { requestedAction, resolvedAction: exactAlias[0].key };
2045
+ return { requestedAction, resolvedAction: exactAlias[0].key, resolvedActionMeta: exactAlias[0].action || null };
2033
2046
  }
2034
2047
  if (exactAlias.length > 1) {
2035
2048
  throw new Error(
@@ -2045,7 +2058,7 @@ async function resolveActionSelection(ctx, flags) {
2045
2058
  entry.aliases.some((a) => a.toLowerCase().includes(requestedLower))
2046
2059
  );
2047
2060
  if (fuzzy.length === 1) {
2048
- return { requestedAction, resolvedAction: fuzzy[0].key };
2061
+ return { requestedAction, resolvedAction: fuzzy[0].key, resolvedActionMeta: fuzzy[0].action || null };
2049
2062
  }
2050
2063
  if (fuzzy.length > 1) {
2051
2064
  throw new Error(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdfy/agent-cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Thirdfy Agent CLI for onboarding, governance preflight, execute-intent, and status polling.",
5
5
  "type": "module",
6
6
  "bin": {