@anythingai/cli 0.1.2 → 0.1.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@anythingai/cli` are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Changed
11
+
12
+ - **Breaking:** `--env` now accepts only lowercase values (`development`,
13
+ `preview`, `production`). The uppercase forms (`DEVELOPMENT`, `PREVIEW`,
14
+ `PRODUCTION`) that 0.0.x silently accepted no longer validate — pass the
15
+ lowercase form instead.
16
+
17
+ ### Fixed
18
+
19
+ - `--json` failures now write the error envelope to stdout (was stderr), so
20
+ `anything … --json | jq` receives the payload on failure as well as success.
21
+ - Strict-mode (argument-validation) error envelopes no longer leak positional
22
+ values into `command`; the field is now the canonical command path (e.g.
23
+ `orgs get`, `members invite`), keeping IDs and emails out of the envelope.
24
+ - Silenced the yargs `"version" is a reserved word` warning emitted by
25
+ `anything update` / `anything update --check`.
26
+ - `domains add` now rejects RFC 2606 reserved TLDs (`.invalid`, `.example`,
27
+ `.test`, `.localhost`) before the network round-trip.
28
+ - Deployment-failure `buildLogs` are now emitted as an array of lines
29
+ (`string[]`) in the JSON envelope instead of one newline-joined string.
package/dist/js/bin.mjs CHANGED
@@ -3069,7 +3069,7 @@ function errorCodeFromHttpStatus(status) {
3069
3069
 
3070
3070
  //#endregion
3071
3071
  //#region package.json
3072
- var version = "0.1.2";
3072
+ var version = "0.1.4";
3073
3073
 
3074
3074
  //#endregion
3075
3075
  //#region generated/core/bodySerializer.gen.ts
@@ -4576,13 +4576,19 @@ var AnythingApiClient = class {
4576
4576
  }));
4577
4577
  }
4578
4578
  async listProjectFiles({ projectGroupId }) {
4579
- return this.toResult(await getV0ApiProjectsByProjectGroupIdFiles({
4580
- client: this.client,
4581
- path: { projectGroupId }
4582
- })).andThen((data) => "files" in data ? ok(data) : err({
4583
- message: "Unexpected API response format",
4584
- status: 200
4585
- }));
4579
+ const fetchOnce = async () => {
4580
+ return this.toResult(await getV0ApiProjectsByProjectGroupIdFiles({
4581
+ client: this.client,
4582
+ path: { projectGroupId }
4583
+ })).andThen((data) => "files" in data ? ok({ files: data.files ?? [] }) : err({
4584
+ message: "Unexpected API response format",
4585
+ status: 200
4586
+ }));
4587
+ };
4588
+ const first = await fetchOnce();
4589
+ if (first.isErr() || first.value.files.length > 0) return first;
4590
+ await new Promise((resolve) => setTimeout(resolve, 750));
4591
+ return fetchOnce();
4586
4592
  }
4587
4593
  async getProjectFile({ projectGroupId, path }) {
4588
4594
  return this.toResult(await getV0ApiProjectsByProjectGroupIdFiles({
@@ -4852,6 +4858,11 @@ var AnythingApiClient = class {
4852
4858
  function printJson(data) {
4853
4859
  console.log(JSON.stringify(data, null, 2));
4854
4860
  }
4861
+ function buildLogsToLines(buildLogs) {
4862
+ const lines = buildLogs.split("\n");
4863
+ if (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
4864
+ return lines;
4865
+ }
4855
4866
  function printSuccess(message) {
4856
4867
  console.log(styleText("green", message));
4857
4868
  }
@@ -4900,15 +4911,58 @@ function extractErrorCode(details) {
4900
4911
  const parsed = DetailsWithCodeSchema.safeParse(details);
4901
4912
  return parsed.success ? parsed.data.code : null;
4902
4913
  }
4914
+ function resolveErrorCode({ error, exitCode, codeOverride }) {
4915
+ const status = "status" in error ? error.status ?? null : null;
4916
+ const details = "details" in error ? error.details : void 0;
4917
+ return codeOverride ?? extractErrorCode(details) ?? (status === null && exitCode !== void 0 ? errorCodeFromExitCode(exitCode) : errorCodeFromHttpStatus(status));
4918
+ }
4919
+ function outputStreamError({ argv, command, error, hint, exitCode, buildLogs, code: codeOverride }) {
4920
+ const status = "status" in error ? error.status ?? null : null;
4921
+ process.exitCode = exitCode ?? exitCodeFromHttpStatus(status);
4922
+ if (!argv.json && !argv.quiet) {
4923
+ outputError({
4924
+ argv,
4925
+ command,
4926
+ error,
4927
+ hint,
4928
+ exitCode,
4929
+ buildLogs,
4930
+ code: codeOverride
4931
+ });
4932
+ return;
4933
+ }
4934
+ const code = resolveErrorCode({
4935
+ error,
4936
+ exitCode,
4937
+ codeOverride
4938
+ });
4939
+ const retryAfter = "retryAfter" in error && typeof error.retryAfter === "number" ? error.retryAfter : null;
4940
+ const resolvedHint = hint ?? ("hint" in error && typeof error.hint === "string" ? error.hint : void 0);
4941
+ printNdjson({
4942
+ type: "result",
4943
+ ok: false,
4944
+ error: {
4945
+ code,
4946
+ message: error.message,
4947
+ ...resolvedHint ? { hint: resolvedHint } : {},
4948
+ ...retryAfter !== null ? { retry_after_seconds: retryAfter } : {},
4949
+ ...buildLogs ? { buildLogs: buildLogsToLines(buildLogs) } : {}
4950
+ }
4951
+ });
4952
+ }
4903
4953
  function outputError({ argv, command, error, hint, exitCode, buildLogs, code: codeOverride }) {
4904
4954
  const status = "status" in error ? error.status ?? null : null;
4905
4955
  const details = "details" in error ? error.details : void 0;
4906
4956
  const retryAfter = "retryAfter" in error && typeof error.retryAfter === "number" ? error.retryAfter : null;
4907
4957
  const resolvedHint = hint ?? ("hint" in error && typeof error.hint === "string" ? error.hint : void 0);
4908
4958
  process.exitCode = exitCode ?? exitCodeFromHttpStatus(status);
4909
- const code = codeOverride ?? extractErrorCode(details) ?? (status === null && exitCode !== void 0 ? errorCodeFromExitCode(exitCode) : errorCodeFromHttpStatus(status));
4959
+ const code = resolveErrorCode({
4960
+ error,
4961
+ exitCode,
4962
+ codeOverride
4963
+ });
4910
4964
  if (argv.json || argv.quiet) {
4911
- console.error(JSON.stringify({
4965
+ console.log(JSON.stringify({
4912
4966
  ok: false,
4913
4967
  command,
4914
4968
  error: {
@@ -4916,7 +4970,7 @@ function outputError({ argv, command, error, hint, exitCode, buildLogs, code: co
4916
4970
  message: error.message,
4917
4971
  ...resolvedHint ? { hint: resolvedHint } : {},
4918
4972
  ...retryAfter !== null ? { retry_after_seconds: retryAfter } : {},
4919
- ...buildLogs ? { buildLogs } : {}
4973
+ ...buildLogs ? { buildLogs: buildLogsToLines(buildLogs) } : {}
4920
4974
  }
4921
4975
  }, null, 2));
4922
4976
  return;
@@ -5373,7 +5427,7 @@ async function selectAndSetOrg({ config, json, nonInteractive }) {
5373
5427
  return choice;
5374
5428
  }
5375
5429
  }
5376
- const recommended = orgs.find((org) => BigInt(org.creditBalance) > 0n) ?? orgs[0];
5430
+ const recommended = orgs.find((org) => org.creditsBalance > 0) ?? orgs[0];
5377
5431
  if (!recommended) return null;
5378
5432
  if (!json) {
5379
5433
  console.log();
@@ -6645,11 +6699,19 @@ function toPublicDomain(domain) {
6645
6699
  //#region src/commands/domain-add.ts
6646
6700
  const COMMAND$19 = "domains add";
6647
6701
  const HOSTNAME_PATTERN = /^(?=.{1,253}$)([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
6702
+ const RESERVED_TLDS = new Set([
6703
+ "invalid",
6704
+ "example",
6705
+ "test",
6706
+ "localhost"
6707
+ ]);
6648
6708
  function domainValidationError(domain) {
6649
6709
  if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(domain)) return `Enter a bare hostname without a scheme (got "${domain}"). Example: app.example.com`;
6650
6710
  if (domain.includes("/") || /\s/.test(domain)) return `Invalid domain "${domain}". Enter a bare hostname like app.example.com`;
6651
6711
  if (!domain.includes(".")) return `Invalid domain "${domain}". A domain must include a dot, e.g. app.example.com`;
6652
6712
  if (!HOSTNAME_PATTERN.test(domain)) return `Invalid domain "${domain}". Enter a valid hostname like app.example.com`;
6713
+ const tld = domain.split(".").pop()?.toLowerCase() ?? "";
6714
+ if (RESERVED_TLDS.has(tld)) return `Invalid domain "${domain}". ".${tld}" is a reserved TLD that cannot be used for a real domain. Use a registered domain like app.example.com`;
6653
6715
  return null;
6654
6716
  }
6655
6717
  const domainAddCommand = {
@@ -8490,7 +8552,7 @@ const llmContextCommand = {
8490
8552
  id: org.id,
8491
8553
  name: org.name,
8492
8554
  plan: org.plan,
8493
- hasCredits: BigInt(org.creditBalance) > 0n
8555
+ hasCredits: org.creditsBalance > 0
8494
8556
  }))
8495
8557
  };
8496
8558
  } catch {}
@@ -8912,18 +8974,6 @@ const membersCommand = {
8912
8974
  handler: () => {}
8913
8975
  };
8914
8976
 
8915
- //#endregion
8916
- //#region src/format-credits.ts
8917
- const HUMAN_READABLE_FACTOR = 10000000n;
8918
- const formatter = Intl.NumberFormat("en", {
8919
- notation: "compact",
8920
- maximumSignificantDigits: 3
8921
- });
8922
- const humanizeCredits = (credits) => {
8923
- const normalized = BigInt(credits) * 100n / HUMAN_READABLE_FACTOR;
8924
- return formatter.format(Math.ceil(Number(normalized) / 100));
8925
- };
8926
-
8927
8977
  //#endregion
8928
8978
  //#region src/commands/org-members.ts
8929
8979
  const orgMembersCommand = {
@@ -9048,9 +9098,6 @@ async function loadOrganizations(argv, command) {
9048
9098
  }
9049
9099
  return result.value.organizations;
9050
9100
  }
9051
- function formatCredits$1(creditBalance) {
9052
- return `${humanizeCredits(creditBalance)} credits`;
9053
- }
9054
9101
  const getCommand = {
9055
9102
  command: "get <organizationId>",
9056
9103
  describe: "Inspect a single organization",
@@ -9086,7 +9133,7 @@ const getCommand = {
9086
9133
  printLabel("ID", organization.id);
9087
9134
  printLabel("Plan", organization.planDisplayName);
9088
9135
  printLabel("Paid", organization.isPaid ? "yes" : "no");
9089
- printLabel("Credits", formatCredits$1(organization.creditBalance));
9136
+ printLabel("Credits", `${organization.creditsBalance} credits`);
9090
9137
  printLabel("Plan Code", organization.plan);
9091
9138
  }
9092
9139
  };
@@ -9590,13 +9637,25 @@ const createCommand = {
9590
9637
  const DEPLOY_POLL_INTERVAL_MS = 3e3;
9591
9638
  const DEPLOY_POLL_TIMEOUT_MS = 6e5;
9592
9639
  const DEPLOY_JITTER_MS = 500;
9640
+ const MAX_CONSECUTIVE_POLL_ERRORS = 5;
9593
9641
  const TERMINAL_STATUSES = new Set(["SUCCESS", "FAILED"]);
9594
9642
  async function waitForDeployment({ client, deploymentId, emit }) {
9595
9643
  const deadline = Date.now() + DEPLOY_POLL_TIMEOUT_MS;
9596
9644
  let lastStatus = null;
9645
+ let consecutiveErrors = 0;
9597
9646
  while (Date.now() < deadline) {
9598
9647
  const result = await client.getDeployment({ deploymentId });
9599
- if (result.isErr()) return err(result.error);
9648
+ if (result.isErr()) {
9649
+ consecutiveErrors += 1;
9650
+ if (consecutiveErrors >= MAX_CONSECUTIVE_POLL_ERRORS) return ok({
9651
+ outcome: "unconfirmed",
9652
+ deploymentId,
9653
+ reason: `Could not confirm deployment status after ${consecutiveErrors} consecutive polling errors (last: ${result.error.message}).`
9654
+ });
9655
+ await setTimeout$1(DEPLOY_POLL_INTERVAL_MS + Math.random() * DEPLOY_JITTER_MS);
9656
+ continue;
9657
+ }
9658
+ consecutiveErrors = 0;
9600
9659
  const { deployment } = result.value;
9601
9660
  if (deployment.status !== lastStatus) {
9602
9661
  lastStatus = deployment.status;
@@ -9623,10 +9682,12 @@ async function waitForDeployment({ client, deploymentId, emit }) {
9623
9682
  * error info if the deployment did not succeed, or null if it succeeded.
9624
9683
  */
9625
9684
  function getDeploymentError({ result, statusCommand }) {
9626
- if (result.outcome === "timeout") return {
9627
- message: `Deployment timed out. Check status with: ${statusCommand}`,
9685
+ if (result.outcome === "timeout" || result.outcome === "unconfirmed") return {
9686
+ message: `${result.outcome === "timeout" ? "Deployment did not reach a terminal status before the wait timed out" : result.reason} The deploy may still be in progress. Resume with: ${statusCommand}`,
9628
9687
  exitCode: 6,
9629
- buildLogs: null
9688
+ buildLogs: null,
9689
+ deploymentId: result.deploymentId,
9690
+ hint: `Resume with: ${statusCommand}`
9630
9691
  };
9631
9692
  if (result.deployment.status === "FAILED") {
9632
9693
  const reason = result.deployment.failureReason ?? null;
@@ -9634,7 +9695,9 @@ function getDeploymentError({ result, statusCommand }) {
9634
9695
  return {
9635
9696
  message: reason ?? (logs ? "Deployment failed. See build logs for details." : "Deployment failed (no logs available)."),
9636
9697
  exitCode: 1,
9637
- buildLogs: logs
9698
+ buildLogs: logs,
9699
+ deploymentId: result.deployment.id,
9700
+ hint: null
9638
9701
  };
9639
9702
  }
9640
9703
  return null;
@@ -9845,11 +9908,12 @@ const publishCommand = {
9845
9908
  argv,
9846
9909
  command: COMMAND$15,
9847
9910
  error: {
9848
- message: deployError.message,
9911
+ message: deployError.deploymentId ? `${deployError.message} (deploymentId: ${deployError.deploymentId})` : deployError.message,
9849
9912
  status: null
9850
9913
  },
9851
9914
  exitCode: deployError.exitCode,
9852
- buildLogs: deployError.buildLogs ?? void 0
9915
+ buildLogs: deployError.buildLogs ?? void 0,
9916
+ hint: deployError.hint ?? void 0
9853
9917
  });
9854
9918
  return;
9855
9919
  }
@@ -9980,20 +10044,24 @@ const list$1 = {
9980
10044
  });
9981
10045
  return;
9982
10046
  }
10047
+ const files = result.value.files;
9983
10048
  if (argv.json && outputSuccess({
9984
10049
  argv,
9985
10050
  command,
9986
- data: result.value
10051
+ data: {
10052
+ files,
10053
+ count: files.length
10054
+ }
9987
10055
  })) return;
9988
10056
  if (argv.quiet) {
9989
- for (const file of result.value.files) console.log(file.path);
10057
+ for (const file of files) console.log(file.path);
9990
10058
  return;
9991
10059
  }
9992
- if (result.value.files.length === 0) {
10060
+ if (files.length === 0) {
9993
10061
  console.log("No files found.");
9994
10062
  return;
9995
10063
  }
9996
- for (const file of result.value.files) console.log(file.path);
10064
+ for (const file of files) console.log(file.path);
9997
10065
  }
9998
10066
  };
9999
10067
  const get$1 = {
@@ -10945,7 +11013,11 @@ const secretEnvironmentChoices = [
10945
11013
  "preview",
10946
11014
  "production"
10947
11015
  ];
10948
- const DEFAULT_SECRET_ENVIRONMENT = "DEVELOPMENT";
11016
+ const ALL_SECRET_ENVIRONMENTS = [
11017
+ "DEVELOPMENT",
11018
+ "PREVIEW",
11019
+ "PRODUCTION"
11020
+ ];
10949
11021
  const add = {
10950
11022
  command: "add <projectId>",
10951
11023
  describe: "Add a secret to an app",
@@ -10964,7 +11036,7 @@ const add = {
10964
11036
  type: "string",
10965
11037
  coerce: (value) => value.toLowerCase(),
10966
11038
  choices: secretEnvironmentChoices,
10967
- describe: "Target environment for the secret"
11039
+ describe: "Target a single environment. Omit to add the secret to all environments (development, preview, production) so it reaches the published app."
10968
11040
  }).option("force", {
10969
11041
  type: "boolean",
10970
11042
  default: false,
@@ -10972,16 +11044,17 @@ const add = {
10972
11044
  }).example("anything projects secrets add <id> --name KEY --value \"secret\"", "Add a secret from an inline value").example("cat secret.txt | anything projects secrets add <id> --name KEY", "Read a secret value from stdin"),
10973
11045
  handler: async (argv) => {
10974
11046
  const command = "projects secrets add";
11047
+ const targetEnvironments = argv.env ? [argv.env.toUpperCase()] : [...ALL_SECRET_ENVIRONMENTS];
10975
11048
  if (argv["dry-run"]) {
10976
11049
  outputDryRun({
10977
11050
  argv,
10978
11051
  command,
10979
- plannedActions: [{
11052
+ plannedActions: targetEnvironments.map((environment) => ({
10980
11053
  action: "add_secret",
10981
11054
  projectGroupId: argv.projectId,
10982
11055
  name: argv.name,
10983
- ...argv.env ? { environment: argv.env.toUpperCase() } : {}
10984
- }]
11056
+ environment
11057
+ }))
10985
11058
  });
10986
11059
  return;
10987
11060
  }
@@ -11019,16 +11092,16 @@ const add = {
11019
11092
  return;
11020
11093
  }
11021
11094
  const client = new AnythingApiClient(config.value);
11022
- const targetEnvironment = argv.env ? argv.env.toUpperCase() : DEFAULT_SECRET_ENVIRONMENT;
11023
11095
  if (!argv.force) {
11024
11096
  const existing = await client.listSecrets({ projectGroupId: argv.projectId });
11025
11097
  if (existing.isOk()) {
11026
- if (existing.value.secrets.find((secret) => secret.displayName === argv.name && secret.environment === targetEnvironment)) {
11098
+ const collisions = targetEnvironments.filter((environment) => existing.value.secrets.some((secret) => secret.displayName === argv.name && secret.environment === environment));
11099
+ if (collisions.length > 0) {
11027
11100
  outputError({
11028
11101
  argv,
11029
11102
  command,
11030
11103
  error: {
11031
- message: `A secret named "${argv.name}" already exists in ${targetEnvironment}.`,
11104
+ message: `A secret named "${argv.name}" already exists in ${collisions.join(", ")}.`,
11032
11105
  status: 409
11033
11106
  },
11034
11107
  hint: "Remove the existing secret first, or pass --force to create a suffixed sibling."
@@ -11037,31 +11110,41 @@ const add = {
11037
11110
  }
11038
11111
  }
11039
11112
  }
11040
- const result = await client.addSecret({
11041
- projectGroupId: argv.projectId,
11042
- displayName: argv.name,
11043
- value: valueResult.value,
11044
- environment: targetEnvironment
11045
- });
11046
- if (result.isErr()) {
11047
- outputError({
11048
- argv,
11049
- command,
11050
- error: result.error
11113
+ const added = [];
11114
+ for (const environment of targetEnvironments) {
11115
+ const result = await client.addSecret({
11116
+ projectGroupId: argv.projectId,
11117
+ displayName: argv.name,
11118
+ value: valueResult.value,
11119
+ environment
11120
+ });
11121
+ if (result.isErr()) {
11122
+ outputError({
11123
+ argv,
11124
+ command,
11125
+ error: result.error
11126
+ });
11127
+ return;
11128
+ }
11129
+ added.push({
11130
+ id: result.value.secret.id,
11131
+ envKey: result.value.secret.envKey,
11132
+ environment: result.value.secret.environment
11051
11133
  });
11052
- return;
11053
11134
  }
11135
+ const environments = added.map((s) => s.environment);
11054
11136
  if (outputSuccess({
11055
11137
  argv,
11056
11138
  command,
11057
- data: result.value,
11058
- primaryId: result.value.secret.id
11139
+ data: {
11140
+ secrets: added,
11141
+ environments
11142
+ },
11143
+ primaryId: added[0]?.id
11059
11144
  })) return;
11060
- const s = result.value.secret;
11061
- printSuccess("Secret added.");
11062
- printLabel("ID", s.id);
11063
- printLabel("Env Key", s.envKey);
11064
- printLabel("Environment", s.environment);
11145
+ printSuccess(`Secret added to ${environments.join(", ")}.`);
11146
+ printLabel("Env Key", added[0]?.envKey ?? argv.name);
11147
+ for (const s of added) printLabel(`ID (${s.environment})`, s.id);
11065
11148
  }
11066
11149
  };
11067
11150
  const remove = {
@@ -11948,7 +12031,7 @@ const shipCommand = {
11948
12031
  apiUrl: argv.apiUrl
11949
12032
  });
11950
12033
  if (config.isErr()) {
11951
- outputError({
12034
+ outputStreamError({
11952
12035
  argv,
11953
12036
  command: COMMAND$4,
11954
12037
  error: {
@@ -11970,7 +12053,7 @@ const shipCommand = {
11970
12053
  nonInteractive: isNonInteractive(argv)
11971
12054
  });
11972
12055
  if (!orgResult.ok) {
11973
- outputError({
12056
+ outputStreamError({
11974
12057
  argv,
11975
12058
  command: COMMAND$4,
11976
12059
  error: {
@@ -11993,7 +12076,7 @@ const shipCommand = {
11993
12076
  name: argv.name ?? null
11994
12077
  });
11995
12078
  if (createResult.isErr()) {
11996
- outputError({
12079
+ outputStreamError({
11997
12080
  argv,
11998
12081
  command: COMMAND$4,
11999
12082
  error: createResult.error
@@ -12021,7 +12104,7 @@ const shipCommand = {
12021
12104
  createNewThread: false
12022
12105
  });
12023
12106
  if (genResult.isErr()) {
12024
- outputError({
12107
+ outputStreamError({
12025
12108
  argv,
12026
12109
  command: COMMAND$4,
12027
12110
  error: genResult.error
@@ -12085,7 +12168,7 @@ const shipCommand = {
12085
12168
  slug: argv.slug ?? null
12086
12169
  });
12087
12170
  if (publishResult.isErr()) {
12088
- outputError({
12171
+ outputStreamError({
12089
12172
  argv,
12090
12173
  command: COMMAND$4,
12091
12174
  error: publishResult.error
@@ -12100,7 +12183,7 @@ const shipCommand = {
12100
12183
  emit
12101
12184
  });
12102
12185
  if (deployResult.isErr()) {
12103
- outputError({
12186
+ outputStreamError({
12104
12187
  argv,
12105
12188
  command: COMMAND$4,
12106
12189
  error: deployResult.error
@@ -12112,15 +12195,16 @@ const shipCommand = {
12112
12195
  statusCommand: `anything projects publish status ${projectGroupId} ${deploymentId}`
12113
12196
  });
12114
12197
  if (deployError) {
12115
- outputError({
12198
+ outputStreamError({
12116
12199
  argv,
12117
12200
  command: COMMAND$4,
12118
12201
  error: {
12119
- message: deployError.message,
12202
+ message: deployError.deploymentId ? `${deployError.message} (deploymentId: ${deployError.deploymentId})` : deployError.message,
12120
12203
  status: null
12121
12204
  },
12122
12205
  exitCode: deployError.exitCode,
12123
- buildLogs: deployError.buildLogs ?? void 0
12206
+ buildLogs: deployError.buildLogs ?? void 0,
12207
+ hint: deployError.hint ?? void 0
12124
12208
  });
12125
12209
  return;
12126
12210
  }
@@ -12418,8 +12502,9 @@ const switchCommand = {
12418
12502
  const PACKAGE_NAME = "@anythingai/cli";
12419
12503
  const REGISTRY_BASE_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
12420
12504
  const REGISTRY_URL = `${REGISTRY_BASE_URL}/latest`;
12421
- const CHECK_INTERVAL_MS = 1440 * 60 * 1e3;
12422
- const NOTICE_FETCH_TIMEOUT_MS = 1500;
12505
+ const INTERNAL_UPDATE_CHECK_ARG = "__update-check";
12506
+ const CHECK_INTERVAL_MS = 10800 * 1e3;
12507
+ const REFRESH_FETCH_TIMEOUT_MS = 1e4;
12423
12508
  const latestManifestSchema = z.object({ version: z.string() });
12424
12509
  function isNewerVersion(candidate, current) {
12425
12510
  const core = (v) => (v.split("-")[0] ?? "").split(".").map((part) => Number.parseInt(part, 10));
@@ -12467,30 +12552,62 @@ function printUpdateNotice({ current, latest }) {
12467
12552
  ""
12468
12553
  ].join("\n"));
12469
12554
  }
12470
- async function notifyIfUpdateAvailable(now) {
12555
+ function spawnBackgroundRefresh() {
12556
+ const entry = process.argv[1];
12557
+ if (!entry) return;
12558
+ try {
12559
+ spawn(process.execPath, [entry, INTERNAL_UPDATE_CHECK_ARG], {
12560
+ detached: true,
12561
+ stdio: "ignore",
12562
+ windowsHide: true,
12563
+ env: backgroundRefreshEnv()
12564
+ }).unref();
12565
+ } catch {}
12566
+ }
12567
+ function backgroundRefreshEnv() {
12568
+ const allowed = [
12569
+ "PATH",
12570
+ "HOME",
12571
+ "XDG_CONFIG_HOME",
12572
+ "APPDATA",
12573
+ "LOCALAPPDATA",
12574
+ "SystemRoot"
12575
+ ];
12576
+ const env = {};
12577
+ for (const key of allowed) {
12578
+ const value = process.env[key];
12579
+ if (value !== void 0) env[key] = value;
12580
+ }
12581
+ return env;
12582
+ }
12583
+ async function refreshUpdateCheckCache(now) {
12584
+ recordUpdateCheck({
12585
+ checkedAt: now,
12586
+ latestVersion: await fetchLatestVersion({ timeoutMs: REFRESH_FETCH_TIMEOUT_MS })
12587
+ });
12588
+ }
12589
+ function notifyIfUpdateAvailable(now) {
12471
12590
  const state = getUpdateCheckState();
12472
- let latest = state.latestKnownVersion;
12473
- if (state.checkedAt === null || now - state.checkedAt >= CHECK_INTERVAL_MS) {
12474
- const fetched = await fetchLatestVersion({ timeoutMs: NOTICE_FETCH_TIMEOUT_MS });
12475
- recordUpdateCheck({
12476
- checkedAt: now,
12477
- latestVersion: fetched
12478
- });
12479
- if (fetched) latest = fetched;
12480
- }
12481
- if (!latest || !isNewerVersion(latest, CLI_VERSION)) return;
12482
- if (state.notifiedVersion === latest) return;
12483
- printUpdateNotice({
12484
- current: CLI_VERSION,
12485
- latest
12591
+ const latest = state.latestKnownVersion;
12592
+ if (latest && isNewerVersion(latest, CLI_VERSION) && state.notifiedVersion !== latest) {
12593
+ printUpdateNotice({
12594
+ current: CLI_VERSION,
12595
+ latest
12596
+ });
12597
+ recordUpdateNotified(latest);
12598
+ }
12599
+ if (!(state.checkedAt === null || now - state.checkedAt >= CHECK_INTERVAL_MS)) return;
12600
+ recordUpdateCheck({
12601
+ checkedAt: now,
12602
+ latestVersion: null
12486
12603
  });
12487
- recordUpdateNotified(latest);
12604
+ spawnBackgroundRefresh();
12488
12605
  }
12489
- async function maybeNotifyUpdate(argv, now) {
12606
+ function maybeNotifyUpdate(argv, now) {
12490
12607
  if (argv.json || argv.quiet) return;
12491
12608
  if (isNonInteractive(argv)) return;
12492
12609
  if (!process.stderr.isTTY) return;
12493
- await notifyIfUpdateAvailable(now);
12610
+ notifyIfUpdateAvailable(now);
12494
12611
  }
12495
12612
 
12496
12613
  //#endregion
@@ -12580,7 +12697,7 @@ function runInstall({ command, args, capture }) {
12580
12697
  const updateCommand = {
12581
12698
  command: "update [version]",
12582
12699
  describe: "Update the CLI to the latest (or a specific) published version",
12583
- builder: (yargs) => yargs.positional("version", {
12700
+ builder: (yargs) => yargs.version(false).positional("version", {
12584
12701
  type: "string",
12585
12702
  describe: "A specific published version to install (defaults to the latest)"
12586
12703
  }).option("check", {
@@ -12753,9 +12870,6 @@ const updateCommand = {
12753
12870
 
12754
12871
  //#endregion
12755
12872
  //#region src/commands/user.ts
12756
- function formatCredits(creditBalance) {
12757
- return `${humanizeCredits(creditBalance)} credits`;
12758
- }
12759
12873
  const COMMAND = "user";
12760
12874
  const userCommand = {
12761
12875
  command: "user",
@@ -12794,14 +12908,14 @@ const userCommand = {
12794
12908
  }
12795
12909
  const activeOrgId = getStoredOrgId();
12796
12910
  const defaultOrganization = result.value.organizations[0] ?? null;
12797
- const organizationWithCredits = result.value.organizations.find((org) => BigInt(org.creditBalance) > 0n) ?? null;
12798
- const recommendedOrganization = defaultOrganization !== null && BigInt(defaultOrganization.creditBalance) > 0n ? defaultOrganization : organizationWithCredits;
12911
+ const organizationWithCredits = result.value.organizations.find((org) => org.creditsBalance > 0) ?? null;
12912
+ const recommendedOrganization = defaultOrganization !== null && defaultOrganization.creditsBalance > 0 ? defaultOrganization : organizationWithCredits;
12799
12913
  const credentialSource = env.ANYTHING_API_KEY ? "env" : configExists() ? "config" : "unknown";
12800
12914
  const checks = {
12801
12915
  hasOrganizations: result.value.organizations.length > 0,
12802
12916
  hasPaidOrganization: result.value.organizations.some((org) => org.isPaid),
12803
12917
  hasCredits: organizationWithCredits !== null,
12804
- defaultOrganizationHasCredits: defaultOrganization !== null ? BigInt(defaultOrganization.creditBalance) > 0n : null
12918
+ defaultOrganizationHasCredits: defaultOrganization !== null ? defaultOrganization.creditsBalance > 0 : null
12805
12919
  };
12806
12920
  const activeOrg = activeOrgId ? result.value.organizations.find((o) => o.id === activeOrgId) ?? null : null;
12807
12921
  if (argv.quiet && !argv.json) {
@@ -12870,7 +12984,7 @@ const userCommand = {
12870
12984
  org.id === activeOrgId ? "*" : "",
12871
12985
  org.name,
12872
12986
  org.planDisplayName,
12873
- formatCredits(org.creditBalance),
12987
+ `${org.creditsBalance} credits`,
12874
12988
  org.id
12875
12989
  ])
12876
12990
  });
@@ -12882,7 +12996,7 @@ const userCommand = {
12882
12996
  if (!activeOrgId && recommendedOrganization !== null) {
12883
12997
  console.log();
12884
12998
  console.log(`No active organization set. Run \`anything orgs set ${recommendedOrganization.id}\` to set one.`);
12885
- } else if (activeOrg !== null && BigInt(activeOrg.creditBalance) === 0n && recommendedOrganization !== null && recommendedOrganization.id !== activeOrg.id) {
12999
+ } else if (activeOrg !== null && activeOrg.creditsBalance === 0 && recommendedOrganization !== null && recommendedOrganization.id !== activeOrg.id) {
12886
13000
  console.log();
12887
13001
  console.log(`Active organization has no credits. Run \`anything orgs set ${recommendedOrganization.id}\` to switch.`);
12888
13002
  }
@@ -13036,6 +13150,16 @@ const watchCommand = {
13036
13150
 
13037
13151
  //#endregion
13038
13152
  //#region src/cli.ts
13153
+ const REGISTERED_COMMAND_PATHS = (() => {
13154
+ const paths = /* @__PURE__ */ new Set();
13155
+ for (const { name } of commandTree) {
13156
+ const words = name.split(" ");
13157
+ for (let i = 1; i <= words.length; i++) paths.add(words.slice(0, i).join(" "));
13158
+ }
13159
+ paths.add("dev");
13160
+ paths.add("update");
13161
+ return paths;
13162
+ })();
13039
13163
  var HandledCliError = class extends Error {};
13040
13164
  function commandPathFromArgv(argv) {
13041
13165
  const words = [];
@@ -13043,7 +13167,15 @@ function commandPathFromArgv(argv) {
13043
13167
  if (token.startsWith("-")) break;
13044
13168
  words.push(token);
13045
13169
  }
13046
- return words.length > 0 ? words.join(" ") : null;
13170
+ const [firstWord] = words;
13171
+ if (firstWord === void 0) return null;
13172
+ let matched = "";
13173
+ for (let i = 0; i < words.length; i++) {
13174
+ const candidate = words.slice(0, i + 1).join(" ");
13175
+ if (!REGISTERED_COMMAND_PATHS.has(candidate)) break;
13176
+ matched = candidate;
13177
+ }
13178
+ return matched === "" ? firstWord : matched;
13047
13179
  }
13048
13180
  function createCli(argv) {
13049
13181
  const cli = yargs(argv).scriptName("anything").usage("$0 <command> [options]").example("anything auth login", "Log in via browser").example("anything ship --prompt \"Build a todo app\"", "Create + publish in one shot").example("anything domains list org_123", "List domains for one organization").example("anything orgs", "List your organizations").example("anything orgs get <org-id>", "Inspect one organization").example("anything orgs set <org-id>", "Set the active organization").example("anything orgs members <org-id>", "Inspect collaborators and pending invites").example("anything projects create --prompt todo-app", "Create a new app").example("anything projects generate <project-id> --prompt add-auth", "Iterate on an existing app").example("anything projects publish <project-id> --slug my-app", "Publish an app").example("anything projects get <project-id> --json", "Inspect an app in JSON").example("anything projects rename <project-id> --name \"My App\"", "Rename a project").example("anything databases list --org <org-id>", "List databases for an organization").example("anything deployments list <project-id>", "List deployments for a project").example("anything members invite user@example.com --org org_123", "Invite a member").example("anything update", "Update the CLI to the latest version").example("anything status", "Show current context").example("anything switch", "Interactive org/project picker").example("anything introspect", "Output command tree as JSON").option("json", {
@@ -13075,9 +13207,9 @@ function createCli(argv) {
13075
13207
  type: "string",
13076
13208
  description: "Override the API base URL",
13077
13209
  global: true
13078
- }).middleware(async (args) => {
13210
+ }).middleware((args) => {
13079
13211
  setDevFlagOverride(args.dev === true);
13080
- await maybeNotifyUpdate({
13212
+ maybeNotifyUpdate({
13081
13213
  json: args.json === true,
13082
13214
  quiet: args.quiet === true,
13083
13215
  "non-interactive": args["non-interactive"] === true,
@@ -13112,7 +13244,8 @@ function createCli(argv) {
13112
13244
  function isHandled(err) {
13113
13245
  return err instanceof HandledCliError;
13114
13246
  }
13115
- try {
13247
+ if (process.argv[2] === INTERNAL_UPDATE_CHECK_ARG) refreshUpdateCheckCache(Date.now()).catch(() => {}).finally(() => process.exit(0));
13248
+ else try {
13116
13249
  const result = createCli(hideBin(process.argv)).parse();
13117
13250
  if (result instanceof Promise) result.catch((err) => {
13118
13251
  if (isHandled(err)) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anythingai/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "homepage": "https://anything.com/",
5
5
  "license": "MIT",
6
6
  "bin": {