run402 4.70.3 → 4.70.4

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "surface_version": "4.70.3",
2
+ "surface_version": "4.70.4",
3
3
  "verbs": [
4
4
  "repos create",
5
5
  "repos list",
@@ -9,7 +9,8 @@
9
9
  * into the env var here, at the edge.
10
10
  *
11
11
  * Precedence (highest first):
12
- * 1. --wallet <name> / --profile <name> (flag)
12
+ * 1. --wallet <name> / --profile <name> (flag; under `repos`, only --wallet —
13
+ * `repos create|mirror|recover --profile <name>` is the AWS credential profile)
13
14
  * 2. RUN402_WALLET / RUN402_PROFILE (env)
14
15
  * 3. nearest .run402.local.json/.run402.json (directory binding, walk up)
15
16
  * 4. config.json active_wallet (global `wallets use`)
@@ -41,6 +42,11 @@ export { findBindingKey, bindingFilePath, readBindingFile };
41
42
 
42
43
  const DEFAULT = "default";
43
44
  const GLOBAL_FLAGS = new Set(["--wallet", "--profile"]);
45
+ // `repos` owns `--profile` itself (the AWS credential profile for a BYO
46
+ // destination, a mirror, or a recovery source), so under that command only
47
+ // `--wallet` selects the wallet; RUN402_WALLET and the directory binding still
48
+ // apply. Stripping `--profile` there made the documented s3 flags unreachable.
49
+ const OWNS_PROFILE_FLAG = new Set(["repos"]);
44
50
  // The `wallets` group is the management + escape surface — it must work even
45
51
  // when selection is ambiguous (so you can `wallets unbind`), and it validates
46
52
  // its own positional targets. `init` creates wallets, so it must not fail
@@ -50,7 +56,8 @@ const EXISTENCE_EXEMPT = new Set(["wallets", "init", "doctor"]);
50
56
 
51
57
  /**
52
58
  * Split the global --wallet/--profile flag (and its value) out of argv so the
53
- * subcommand never sees it. Pure: no core imports, no side effects. Returns
59
+ * subcommand never sees it except `--profile` under a command that owns the
60
+ * flag (OWNS_PROFILE_FLAG), which is passed through untouched. Pure: no core imports, no side effects. Returns
54
61
  * the cleaned argv and the selected flag (`{ flag, value }` or null). Last
55
62
  * occurrence wins. A missing value is left as `value: undefined` for
56
63
  * resolveWallet to reject with a precise error.
@@ -58,16 +65,26 @@ const EXISTENCE_EXEMPT = new Set(["wallets", "init", "doctor"]);
58
65
  export function splitWalletFlag(rawArgv = []) {
59
66
  const argv = [];
60
67
  let flag = null;
68
+ // The command word: the first positional that is not the value of a global flag.
69
+ let first;
70
+ for (let i = 0; i < rawArgv.length && first === undefined; i++) {
71
+ const a = rawArgv[i];
72
+ if (typeof a !== "string" || a.startsWith("-")) continue;
73
+ if (i > 0 && GLOBAL_FLAGS.has(rawArgv[i - 1])) continue;
74
+ first = a;
75
+ }
76
+ const ownsProfile = OWNS_PROFILE_FLAG.has(first);
77
+ const isGlobal = (name) => GLOBAL_FLAGS.has(name) && !(ownsProfile && name === "--profile");
61
78
  for (let i = 0; i < rawArgv.length; i++) {
62
79
  const a = rawArgv[i];
63
80
  if (typeof a === "string" && a.startsWith("--") && a.includes("=")) {
64
81
  const name = a.slice(0, a.indexOf("="));
65
- if (GLOBAL_FLAGS.has(name)) {
82
+ if (isGlobal(name)) {
66
83
  flag = { flag: name, value: a.slice(a.indexOf("=") + 1) };
67
84
  continue;
68
85
  }
69
86
  }
70
- if (typeof a === "string" && GLOBAL_FLAGS.has(a)) {
87
+ if (typeof a === "string" && isGlobal(a)) {
71
88
  const next = rawArgv[i + 1];
72
89
  if (next === undefined || (typeof next === "string" && next.startsWith("-"))) {
73
90
  flag = { flag: a, value: undefined };
@@ -71,6 +71,18 @@ describe("splitWalletFlag", () => {
71
71
  assert.deepEqual(r.argv, ["deploy", "apply", "--manifest", "x"]);
72
72
  assert.equal(r.walletFlag.value, "foo");
73
73
  });
74
+ it("leaves --profile to `repos`, which owns it as the AWS credential profile", () => {
75
+ const r = splitWalletFlag(["repos", "create", "byo-1", "--byo", "s3://b/p", "--profile", "acme", "--region", "us-east-1"]);
76
+ assert.equal(r.walletFlag, null);
77
+ assert.deepEqual(r.argv, ["repos", "create", "byo-1", "--byo", "s3://b/p", "--profile", "acme", "--region", "us-east-1"]);
78
+ const m = splitWalletFlag(["--wallet", "w", "repos", "mirror", "s3://m", "--profile=acme"]);
79
+ assert.deepEqual(m.walletFlag, { flag: "--wallet", value: "w" });
80
+ assert.deepEqual(m.argv, ["repos", "mirror", "s3://m", "--profile=acme"]);
81
+ const rec = splitWalletFlag(["repos", "recover", "s3://m", "--out", "./r", "--profile", "acme"]);
82
+ assert.equal(rec.walletFlag, null);
83
+ assert.ok(rec.argv.includes("--profile") && rec.argv.includes("acme"));
84
+ });
85
+
74
86
  it("accepts --profile as an alias", () => {
75
87
  const r = splitWalletFlag(["--profile", "p", "status"]);
76
88
  assert.equal(r.walletFlag.flag, "--profile");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "run402",
3
- "version": "4.70.3",
3
+ "version": "4.70.4",
4
4
  "description": "CLI for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.",
5
5
  "type": "module",
6
6
  "bin": {