@indigoai-us/hq-cli 5.266.0 → 5.267.0

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
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.267.0] — 2026-09-28
6
+
7
+ - Company billing links opened by CLI plan-limit flows now carry cli_limit attribution into checkout telemetry.
8
+
9
+ ### Fixed
10
+
11
+ - Local bots now read the idle inbox backoff flag with a 2 s budget. The
12
+ 150 ms budget timed out from home networks, so bots kept polling every 2 s
13
+ even when the flag was on for them.
14
+
5
15
  ## [5.266.0] — 2026-09-28
6
16
 
7
17
  ### Added
@@ -6,8 +6,9 @@ export interface PlanLimitUpgradeUrlChoices {
6
6
  legacyUrl: string;
7
7
  }
8
8
  export declare function isPlanLimitUpgradeFallbackEnabled(): boolean;
9
- /** Resolve a server URL without changing legacy behavior while the flag is off. */
9
+ /** Resolve and attribute the final selected company billing destination. */
10
10
  export declare function selectPlanLimitUpgradeUrl(companySlug: string | undefined, choices: PlanLimitUpgradeUrlChoices): string;
11
- /** Keep a caller's previous URL until the hq-flags rollout is enabled. */
11
+ export declare function withCliLimitEntrySurface(value: string): string;
12
+ /** Keep the existing destination and flag behavior while labeling company limit links. */
12
13
  export declare function planLimitUpgradeFallbackUrl(companySlug: string | undefined, previousFallbackUrl: string): string;
13
14
  //# sourceMappingURL=plan-limit-upgrade-url.d.ts.map
@@ -13,23 +13,62 @@ function companyBillingUrl(companySlug) {
13
13
  return null;
14
14
  const slug = companySlug?.trim();
15
15
  const route = slug
16
- ? `/companies/${encodeURIComponent(slug)}/billing?upgrade=1`
16
+ ? `/companies/${encodeURIComponent(slug)}/billing?upgrade=1&entrySurface=cli_limit`
17
17
  : "/billing";
18
18
  return `${origin}${route}`;
19
19
  }
20
- /** Resolve a server URL without changing legacy behavior while the flag is off. */
20
+ /** Resolve and attribute the final selected company billing destination. */
21
21
  export function selectPlanLimitUpgradeUrl(companySlug, choices) {
22
- if (!isPlanLimitUpgradeFallbackEnabled())
23
- return choices.legacyUrl;
24
- const topLevelUrl = choices.topLevelUrl?.trim() || undefined;
25
- const nestedUrl = choices.nestedUrl?.trim() || undefined;
26
- const generatedUrl = companyBillingUrl(companySlug);
27
- if (companySlug?.trim()) {
28
- return generatedUrl ?? topLevelUrl ?? nestedUrl ?? choices.legacyUrl;
22
+ let selected;
23
+ if (!isPlanLimitUpgradeFallbackEnabled()) {
24
+ selected = choices.legacyUrl;
29
25
  }
30
- return topLevelUrl ?? nestedUrl ?? generatedUrl ?? choices.legacyUrl;
26
+ else {
27
+ const topLevelUrl = choices.topLevelUrl?.trim() || undefined;
28
+ const nestedUrl = choices.nestedUrl?.trim() || undefined;
29
+ const generatedUrl = companyBillingUrl(companySlug);
30
+ if (companySlug?.trim()) {
31
+ selected = generatedUrl ?? topLevelUrl ?? nestedUrl ?? choices.legacyUrl;
32
+ }
33
+ else {
34
+ selected = topLevelUrl ?? nestedUrl ?? generatedUrl ?? choices.legacyUrl;
35
+ }
36
+ }
37
+ return withCliLimitEntrySurface(selected);
38
+ }
39
+ export function withCliLimitEntrySurface(value) {
40
+ try {
41
+ const url = new URL(value);
42
+ if (url.protocol !== "https:" || url.username || url.password)
43
+ return value;
44
+ const callbackUrl = url.searchParams.get("callbackUrl");
45
+ if (callbackUrl) {
46
+ const callback = new URL(callbackUrl, url.origin);
47
+ const parts = callback.pathname.split("/").filter(Boolean);
48
+ if (parts.length === 5 && parts[0] === "api" && parts[1] === "companies" &&
49
+ /^cmp_[A-Za-z0-9_-]+$/.test(parts[2]) && parts[3] === "billing" && parts[4] === "upgrade") {
50
+ callback.searchParams.set("entrySurface", "cli_limit");
51
+ const serializedCallback = /^[a-z][a-z0-9+.-]*:/i.test(callbackUrl)
52
+ ? callback.toString()
53
+ : callbackUrl.startsWith("//")
54
+ ? `//${callback.host}${callback.pathname}${callback.search}${callback.hash}`
55
+ : `${callback.pathname}${callback.search}${callback.hash}`;
56
+ url.searchParams.set("callbackUrl", serializedCallback);
57
+ return url.toString();
58
+ }
59
+ }
60
+ const parts = url.pathname.split("/").filter(Boolean);
61
+ if (parts.length === 3 && parts[0] === "companies" && parts[2] === "billing") {
62
+ url.searchParams.set("entrySurface", "cli_limit");
63
+ return url.toString();
64
+ }
65
+ }
66
+ catch {
67
+ return value;
68
+ }
69
+ return value;
31
70
  }
32
- /** Keep a caller's previous URL until the hq-flags rollout is enabled. */
71
+ /** Keep the existing destination and flag behavior while labeling company limit links. */
33
72
  export function planLimitUpgradeFallbackUrl(companySlug, previousFallbackUrl) {
34
73
  return selectPlanLimitUpgradeUrl(companySlug, {
35
74
  legacyUrl: previousFallbackUrl,
@@ -2,7 +2,7 @@ import { type FlagClient, type FlagClientOptions } from "@indigoai-us/hq-flags-c
2
2
  import { type BotConfig } from "./config.js";
3
3
  export declare const INBOX_POLL_BACKOFF_FLAG = "agents.inbox-poll-backoff-local-cli";
4
4
  export declare const INBOX_POLL_BACKOFF_FLAG_FALLBACK = false;
5
- export declare const INBOX_POLL_BACKOFF_FLAG_TIMEOUT_MS = 150;
5
+ export declare const INBOX_POLL_BACKOFF_FLAG_TIMEOUT_MS = 2000;
6
6
  export declare const INBOX_POLL_BACKOFF_FLAG_CACHE_MS: number;
7
7
  type InboxPollBackoffFlagClient = Pick<FlagClient, "ready" | "isEnabled" | "close">;
8
8
  export interface InboxPollBackoffFlagReaderDependencies {
@@ -5,7 +5,10 @@ import { resolveFlagRegistryEndpoint } from "../flag-registry-endpoint.js";
5
5
  import { effectiveBotCompanies, effectiveBotKind } from "./config.js";
6
6
  export const INBOX_POLL_BACKOFF_FLAG = "agents.inbox-poll-backoff-local-cli";
7
7
  export const INBOX_POLL_BACKOFF_FLAG_FALLBACK = false;
8
- export const INBOX_POLL_BACKOFF_FLAG_TIMEOUT_MS = 150;
8
+ // One read every three minutes on a fresh connection. From a home network the
9
+ // TCP and TLS handshakes plus the resolve call take about 250-400 ms, so a
10
+ // 150 ms budget timed out on every read and kept the gate off.
11
+ export const INBOX_POLL_BACKOFF_FLAG_TIMEOUT_MS = 2_000;
9
12
  export const INBOX_POLL_BACKOFF_FLAG_CACHE_MS = 3 * 60_000;
10
13
  const COMPANY_UID_RE = /^cmp_[A-Za-z0-9]{3,128}$/;
11
14
  export function safeErrorClass(error) {
@@ -4,6 +4,7 @@
4
4
  * message instead of every command parsing and printing a server response.
5
5
  */
6
6
  import { renderPersonalPlanFeatureNotice } from "../lib/plan-limit-nag.js";
7
+ import { withCliLimitEntrySurface } from "../lib/billing/plan-limit-upgrade-url.js";
7
8
  function planGateReason(code, details) {
8
9
  if (details.reason?.trim())
9
10
  return details.reason.trim();
@@ -27,11 +28,12 @@ function planGateReason(code, details) {
27
28
  /** One renderer for server-selected upgrade links across CLI plan refusals. */
28
29
  export function formatUpgradeRefusal(reason, upgradeUrl, options = {}) {
29
30
  const safeUrl = safeUpgradeUrl(upgradeUrl);
30
- if (options.urlOnly && safeUrl)
31
- return safeUrl;
32
- if (!safeUrl)
31
+ const cliLimitUrl = safeUrl ? withCliLimitEntrySurface(safeUrl) : undefined;
32
+ if (options.urlOnly && cliLimitUrl)
33
+ return cliLimitUrl;
34
+ if (!cliLimitUrl)
33
35
  return reason;
34
- return `${reason}\nUpgrade: ${safeUrl}`;
36
+ return `${reason}\nUpgrade: ${cliLimitUrl}`;
35
37
  }
36
38
  function safeUpgradeUrl(value) {
37
39
  if (typeof value !== "string" ||
@@ -94,6 +96,7 @@ export async function offerUpgradeLink(url, deps = {}) {
94
96
  const safeUrl = safeUpgradeUrl(url);
95
97
  if (!safeUrl)
96
98
  return false;
99
+ const cliLimitUrl = withCliLimitEntrySurface(safeUrl);
97
100
  if (!(deps.interactive ?? canOfferTeamUpgrade(deps.argv)))
98
101
  return false;
99
102
  let answer;
@@ -113,11 +116,11 @@ export async function offerUpgradeLink(url, deps = {}) {
113
116
  if (!/^y(?:es)?$/i.test(answer.trim()))
114
117
  return false;
115
118
  if (deps.openUrl) {
116
- await deps.openUrl(safeUrl);
119
+ await deps.openUrl(cliLimitUrl);
117
120
  }
118
121
  else {
119
122
  const { default: open } = await import("open");
120
- await open(safeUrl);
123
+ await open(cliLimitUrl);
121
124
  }
122
125
  return true;
123
126
  }
@@ -26,6 +26,7 @@ export async function upgradeToTeam(opts = {}) {
26
26
  method: "POST",
27
27
  body: {
28
28
  companyUid,
29
+ entrySurface: "cli_limit",
29
30
  successUrl: CHECKOUT_SUCCESS_URL,
30
31
  cancelUrl: CHECKOUT_CANCEL_URL,
31
32
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.266.0",
3
+ "version": "5.267.0",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {