@wave-ai-os/wave-cli 0.1.57 → 0.1.58

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/README.md CHANGED
@@ -103,6 +103,17 @@ Config files are JSON objects using the same keys accepted by `--auth-json-stdin
103
103
  }
104
104
  ```
105
105
 
106
+ For a persistent production login, use the production endpoint explicitly and
107
+ save only that endpoint to the local CLI config. The token remains in the
108
+ configured credential store, not in `config.json`:
109
+
110
+ ```bash
111
+ wave --base-url https://api.ourwave.io login --save-base-url
112
+ ```
113
+
114
+ For a headless environment, add `--no-browser`. This is explicit by design:
115
+ it does not replace a developer's local API endpoint unless they request it.
116
+
106
117
  Entity targeting follows the same explicit-first rule: command flags and positional args, then stdin JSON where supported, then environment/config context for organization and runtime. If a target remains unresolved, the CLI returns a structured JSON error with `suggestedAction`, `suggestedCommands`, or both where the command can provide actionable guidance.
107
118
 
108
119
  ## Discoverability and Diagnostics
package/dist/index.cjs CHANGED
@@ -1793,7 +1793,6 @@ async function runGraphqlMutationCommand(input) {
1793
1793
  // src/commands/runtimeOptions.ts
1794
1794
  var import_node_fs3 = require("fs");
1795
1795
  var import_promises2 = require("fs/promises");
1796
- var import_node_os2 = require("os");
1797
1796
  var import_node_path2 = require("path");
1798
1797
 
1799
1798
  // src/authStorage.ts
@@ -1817,6 +1816,9 @@ function authHome(env = process.env) {
1817
1816
  function tokenPath(env = process.env) {
1818
1817
  return (0, import_node_path.join)(authHome(env), FILE_NAME);
1819
1818
  }
1819
+ function configPath(env = process.env) {
1820
+ return normalize2(env.WAVE_CONFIG_PATH) ?? (0, import_node_path.join)(authHome(env), "config.json");
1821
+ }
1820
1822
  function storageMode(env = process.env) {
1821
1823
  const raw = normalize2(env.WAVE_CLI_AUTH_STORAGE)?.toLowerCase();
1822
1824
  if (raw === "keychain" || raw === "file" || raw === "disabled") return raw;
@@ -1952,6 +1954,25 @@ async function writeStoredToken(token, baseUrl) {
1952
1954
  await writeFileToken(token, baseUrl);
1953
1955
  return { kind: "file", available: true, path: tokenPath() };
1954
1956
  }
1957
+ async function persistBaseUrl(baseUrl, env = process.env) {
1958
+ const path = configPath(env);
1959
+ let existing = {};
1960
+ if ((0, import_node_fs2.existsSync)(path)) {
1961
+ const raw = await (0, import_promises.readFile)(path, "utf8");
1962
+ const parsed = JSON.parse(raw);
1963
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
1964
+ throw new Error(`Wave config file must contain a JSON object: ${path}`);
1965
+ }
1966
+ existing = parsed;
1967
+ }
1968
+ await (0, import_promises.mkdir)((0, import_node_path.dirname)(path), { recursive: true, mode: 448 });
1969
+ await (0, import_promises.writeFile)(path, `${JSON.stringify({ ...existing, baseUrl }, null, 2)}
1970
+ `, {
1971
+ mode: 384
1972
+ });
1973
+ await (0, import_promises.chmod)(path, 384);
1974
+ return path;
1975
+ }
1955
1976
  async function removeStoredToken(baseUrl) {
1956
1977
  const removedKeychain = await deleteKeychainToken(baseUrl);
1957
1978
  const removedFile = await deleteFileToken();
@@ -2252,7 +2273,7 @@ async function resolveWithStoredToken(context) {
2252
2273
  function defaultConfigPath(env) {
2253
2274
  const explicitEnv = normalize3(env.WAVE_CONFIG_PATH);
2254
2275
  if (explicitEnv) return explicitEnv;
2255
- const candidate = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".wave", "config.json");
2276
+ const candidate = (0, import_node_path2.join)(authHome(env), "config.json");
2256
2277
  return (0, import_node_fs3.existsSync)(candidate) ? candidate : void 0;
2257
2278
  }
2258
2279
  async function resolveConfigFileContext(options, env) {
@@ -10216,6 +10237,7 @@ async function runTokenLogin(cmd, opts) {
10216
10237
  }
10217
10238
  const statusData = asRecord6(status.result.data.cliAuthStatus) ?? {};
10218
10239
  const storage = await writeStoredToken(token, baseUrl);
10240
+ const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
10219
10241
  return printEnvelopeAndExit({
10220
10242
  envelope: envelope({
10221
10243
  ok: true,
@@ -10226,6 +10248,8 @@ async function runTokenLogin(cmd, opts) {
10226
10248
  mode: "token",
10227
10249
  tokenStored: true,
10228
10250
  storage,
10251
+ baseUrlSaved: Boolean(configPath2),
10252
+ configPath: configPath2 ?? null,
10229
10253
  status: redactUnknown(statusData, [token])
10230
10254
  }
10231
10255
  })
@@ -10368,6 +10392,7 @@ async function runBrowserLogin(cmd, opts) {
10368
10392
  });
10369
10393
  }
10370
10394
  const storage = await writeStoredToken(cliToken, baseUrl);
10395
+ const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
10371
10396
  return printEnvelopeAndExit({
10372
10397
  envelope: envelope({
10373
10398
  ok: true,
@@ -10379,7 +10404,9 @@ async function runBrowserLogin(cmd, opts) {
10379
10404
  authorizeUrl,
10380
10405
  expiresAt: expiresAt ?? null,
10381
10406
  tokenStored: true,
10382
- storage
10407
+ storage,
10408
+ baseUrlSaved: Boolean(configPath2),
10409
+ configPath: configPath2 ?? null
10383
10410
  }
10384
10411
  })
10385
10412
  });
@@ -10507,7 +10534,7 @@ async function runAuthStatus(cmd) {
10507
10534
  });
10508
10535
  }
10509
10536
  function registerAuthCommands(program) {
10510
- program.command("login").description("Authenticate Wave CLI with a browser login session or provided CLI token").option("--no-browser", "Do not open a browser; include authorizeUrl in the JSON envelope").option("--token [token]", "Store and probe a provided CLI token instead of using browser login").option("--timeout-ms <timeoutMs>", "Login timeout in milliseconds").option("--poll-interval-ms <pollIntervalMs>", "Browser login polling interval in milliseconds").action((opts, cmd) => {
10537
+ program.command("login").description("Authenticate Wave CLI with a browser login session or provided CLI token").option("--no-browser", "Do not open a browser; include authorizeUrl in the JSON envelope").option("--save-base-url", "Persist the resolved API base URL for future Wave CLI commands").option("--token [token]", "Store and probe a provided CLI token instead of using browser login").option("--timeout-ms <timeoutMs>", "Login timeout in milliseconds").option("--poll-interval-ms <pollIntervalMs>", "Browser login polling interval in milliseconds").action((opts, cmd) => {
10511
10538
  const globals = cmd.optsWithGlobals();
10512
10539
  if (opts.token !== void 0 || globals.token !== void 0) {
10513
10540
  return runTokenLogin(cmd, opts);
@@ -15766,7 +15793,7 @@ function attachDiscoveryHelp(program) {
15766
15793
  }
15767
15794
 
15768
15795
  // src/version.ts
15769
- var CLI_VERSION = "0.1.57";
15796
+ var CLI_VERSION = "0.1.58";
15770
15797
 
15771
15798
  // src/cli.ts
15772
15799
  function buildCli(options) {
package/dist/index.js CHANGED
@@ -1792,7 +1792,6 @@ async function runGraphqlMutationCommand(input) {
1792
1792
  // src/commands/runtimeOptions.ts
1793
1793
  import { existsSync as existsSync2 } from "fs";
1794
1794
  import { readFile as readFile2 } from "fs/promises";
1795
- import { homedir as homedir2 } from "os";
1796
1795
  import { join as join2 } from "path";
1797
1796
 
1798
1797
  // src/authStorage.ts
@@ -1800,7 +1799,7 @@ import { execFile } from "child_process";
1800
1799
  import { constants, existsSync } from "fs";
1801
1800
  import { access, mkdir, readFile, rm, stat, writeFile, chmod } from "fs/promises";
1802
1801
  import { homedir } from "os";
1803
- import { join } from "path";
1802
+ import { dirname, join } from "path";
1804
1803
  import { promisify } from "util";
1805
1804
  var execFileAsync = promisify(execFile);
1806
1805
  var KEYCHAIN_SERVICE = "wave-cli";
@@ -1816,6 +1815,9 @@ function authHome(env = process.env) {
1816
1815
  function tokenPath(env = process.env) {
1817
1816
  return join(authHome(env), FILE_NAME);
1818
1817
  }
1818
+ function configPath(env = process.env) {
1819
+ return normalize2(env.WAVE_CONFIG_PATH) ?? join(authHome(env), "config.json");
1820
+ }
1819
1821
  function storageMode(env = process.env) {
1820
1822
  const raw = normalize2(env.WAVE_CLI_AUTH_STORAGE)?.toLowerCase();
1821
1823
  if (raw === "keychain" || raw === "file" || raw === "disabled") return raw;
@@ -1951,6 +1953,25 @@ async function writeStoredToken(token, baseUrl) {
1951
1953
  await writeFileToken(token, baseUrl);
1952
1954
  return { kind: "file", available: true, path: tokenPath() };
1953
1955
  }
1956
+ async function persistBaseUrl(baseUrl, env = process.env) {
1957
+ const path = configPath(env);
1958
+ let existing = {};
1959
+ if (existsSync(path)) {
1960
+ const raw = await readFile(path, "utf8");
1961
+ const parsed = JSON.parse(raw);
1962
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
1963
+ throw new Error(`Wave config file must contain a JSON object: ${path}`);
1964
+ }
1965
+ existing = parsed;
1966
+ }
1967
+ await mkdir(dirname(path), { recursive: true, mode: 448 });
1968
+ await writeFile(path, `${JSON.stringify({ ...existing, baseUrl }, null, 2)}
1969
+ `, {
1970
+ mode: 384
1971
+ });
1972
+ await chmod(path, 384);
1973
+ return path;
1974
+ }
1954
1975
  async function removeStoredToken(baseUrl) {
1955
1976
  const removedKeychain = await deleteKeychainToken(baseUrl);
1956
1977
  const removedFile = await deleteFileToken();
@@ -2251,7 +2272,7 @@ async function resolveWithStoredToken(context) {
2251
2272
  function defaultConfigPath(env) {
2252
2273
  const explicitEnv = normalize3(env.WAVE_CONFIG_PATH);
2253
2274
  if (explicitEnv) return explicitEnv;
2254
- const candidate = join2(homedir2(), ".wave", "config.json");
2275
+ const candidate = join2(authHome(env), "config.json");
2255
2276
  return existsSync2(candidate) ? candidate : void 0;
2256
2277
  }
2257
2278
  async function resolveConfigFileContext(options, env) {
@@ -10215,6 +10236,7 @@ async function runTokenLogin(cmd, opts) {
10215
10236
  }
10216
10237
  const statusData = asRecord6(status.result.data.cliAuthStatus) ?? {};
10217
10238
  const storage = await writeStoredToken(token, baseUrl);
10239
+ const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
10218
10240
  return printEnvelopeAndExit({
10219
10241
  envelope: envelope({
10220
10242
  ok: true,
@@ -10225,6 +10247,8 @@ async function runTokenLogin(cmd, opts) {
10225
10247
  mode: "token",
10226
10248
  tokenStored: true,
10227
10249
  storage,
10250
+ baseUrlSaved: Boolean(configPath2),
10251
+ configPath: configPath2 ?? null,
10228
10252
  status: redactUnknown(statusData, [token])
10229
10253
  }
10230
10254
  })
@@ -10367,6 +10391,7 @@ async function runBrowserLogin(cmd, opts) {
10367
10391
  });
10368
10392
  }
10369
10393
  const storage = await writeStoredToken(cliToken, baseUrl);
10394
+ const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
10370
10395
  return printEnvelopeAndExit({
10371
10396
  envelope: envelope({
10372
10397
  ok: true,
@@ -10378,7 +10403,9 @@ async function runBrowserLogin(cmd, opts) {
10378
10403
  authorizeUrl,
10379
10404
  expiresAt: expiresAt ?? null,
10380
10405
  tokenStored: true,
10381
- storage
10406
+ storage,
10407
+ baseUrlSaved: Boolean(configPath2),
10408
+ configPath: configPath2 ?? null
10382
10409
  }
10383
10410
  })
10384
10411
  });
@@ -10506,7 +10533,7 @@ async function runAuthStatus(cmd) {
10506
10533
  });
10507
10534
  }
10508
10535
  function registerAuthCommands(program) {
10509
- program.command("login").description("Authenticate Wave CLI with a browser login session or provided CLI token").option("--no-browser", "Do not open a browser; include authorizeUrl in the JSON envelope").option("--token [token]", "Store and probe a provided CLI token instead of using browser login").option("--timeout-ms <timeoutMs>", "Login timeout in milliseconds").option("--poll-interval-ms <pollIntervalMs>", "Browser login polling interval in milliseconds").action((opts, cmd) => {
10536
+ program.command("login").description("Authenticate Wave CLI with a browser login session or provided CLI token").option("--no-browser", "Do not open a browser; include authorizeUrl in the JSON envelope").option("--save-base-url", "Persist the resolved API base URL for future Wave CLI commands").option("--token [token]", "Store and probe a provided CLI token instead of using browser login").option("--timeout-ms <timeoutMs>", "Login timeout in milliseconds").option("--poll-interval-ms <pollIntervalMs>", "Browser login polling interval in milliseconds").action((opts, cmd) => {
10510
10537
  const globals = cmd.optsWithGlobals();
10511
10538
  if (opts.token !== void 0 || globals.token !== void 0) {
10512
10539
  return runTokenLogin(cmd, opts);
@@ -15765,7 +15792,7 @@ function attachDiscoveryHelp(program) {
15765
15792
  }
15766
15793
 
15767
15794
  // src/version.ts
15768
- var CLI_VERSION = "0.1.57";
15795
+ var CLI_VERSION = "0.1.58";
15769
15796
 
15770
15797
  // src/cli.ts
15771
15798
  function buildCli(options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wave-ai-os/wave-cli",
3
- "version": "0.1.57",
3
+ "version": "0.1.58",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "wave": "dist/index.js"