@indigoai-us/hq-cli 5.122.2 → 5.123.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 +38 -0
- package/README.md +46 -0
- package/dist/command-catalog.generated.d.ts +6 -3
- package/dist/command-catalog.generated.js +7 -3
- package/dist/commands/dm.d.ts +54 -1
- package/dist/commands/dm.js +204 -8
- package/dist/commands/whoami.d.ts +2 -2
- package/dist/commands/whoami.js +18 -19
- package/dist/lib/billing/plan-lock.d.ts +64 -69
- package/dist/lib/billing/plan-lock.js +230 -161
- package/dist/lib/mesh/api.js +96 -28
- package/dist/lib/mesh/live/daemon/board-refresh.d.ts +4 -1
- package/dist/lib/mesh/live/daemon/board-refresh.js +71 -30
- package/dist/lib/mesh/live/daemon/credentials.d.ts +6 -1
- package/dist/lib/mesh/live/daemon/credentials.js +20 -4
- package/dist/lib/mesh/live/daemon/doctor.d.ts +2 -0
- package/dist/lib/mesh/live/daemon/doctor.js +12 -0
- package/dist/lib/mesh/live/daemon/run.js +6 -1
- package/dist/lib/mesh/live/daemon/state.d.ts +3 -0
- package/dist/utils/cli-telemetry.d.ts +21 -0
- package/dist/utils/cli-telemetry.js +77 -1
- package/package.json +3 -2
|
@@ -1,65 +1,58 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* CLI-side read + render of a workspace's Starter plan-limit nag
|
|
3
|
+
* (starter-plan-hard-limits / US-011, rewritten for US-036, then US-040).
|
|
4
4
|
*
|
|
5
5
|
* Starter (free) workspaces are capped on members, integrations, secrets and
|
|
6
6
|
* agents (deployments and storage nag but never arm a stop). Going over does
|
|
7
7
|
* NOT stop the workspace working (US-033 owner decision 12): everything that
|
|
8
8
|
* exists keeps working, and the only two things that pause are adding new
|
|
9
9
|
* files to the vault and adding new secrets (owner decision 13). Every string
|
|
10
|
-
* this module renders is a nag, never a claim that HQ has stopped.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* module
|
|
10
|
+
* this module renders is a nag, never a claim that HQ has stopped.
|
|
11
|
+
*
|
|
12
|
+
* US-040: hq-pro no longer attaches `planLock` on `/membership/me` or
|
|
13
|
+
* `/v1/billing/usage-limits`. This module reads the nag payload from
|
|
14
|
+
* usage-limits (`planLimits` resource rows, top-level `freeMonth`,
|
|
15
|
+
* `upgradeUrl`) and never a lock object.
|
|
14
16
|
*
|
|
15
17
|
* Copy rule (US-036): no string a customer reads may contain "locked" or
|
|
16
18
|
* "read-only". `plan-lock.test.ts` scans every rendered string for both.
|
|
17
19
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* removes the "n of 5" detail from the notice. An absent field is UNKNOWN, so
|
|
21
|
-
* nothing here ever infers a lock (or an unlock) from missing data
|
|
22
|
-
* (hq-absent-field-never-means-constraining-value).
|
|
20
|
+
* An absent field is UNKNOWN, so nothing here ever infers over-limit from
|
|
21
|
+
* missing data (hq-absent-field-never-means-constraining-value).
|
|
23
22
|
*/
|
|
24
23
|
/**
|
|
25
|
-
*
|
|
26
|
-
* nagging set at these four: `deployments` and `storageBytes` are
|
|
27
|
-
* never appear here.
|
|
28
|
-
* server that adds a fifth dimension renders as the generic line rather than as
|
|
29
|
-
* a false claim about members.
|
|
24
|
+
* Dimensions the bind notice names with a remedy. Owner decision 7 (2026-09-17)
|
|
25
|
+
* fixes the nagging set at these four: `deployments` and `storageBytes` are
|
|
26
|
+
* nag-only and never appear here.
|
|
30
27
|
*/
|
|
28
|
+
export declare const PLAN_LIMIT_REASONS: readonly ["users", "integrations", "secrets", "agents"];
|
|
29
|
+
/** @deprecated US-040 — alias of {@link PLAN_LIMIT_REASONS}. */
|
|
31
30
|
export declare const PLAN_LOCK_REASONS: readonly ["users", "integrations", "secrets", "agents"];
|
|
32
|
-
export type
|
|
33
|
-
/**
|
|
34
|
-
export
|
|
35
|
-
locked: boolean;
|
|
36
|
-
reasons: PlanLockReason[];
|
|
37
|
-
upgradeUrl: string;
|
|
38
|
-
fixOptions: PlanLockFixOptions;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* The remedies hq-pro ships with the lock. The two original fields are always
|
|
42
|
-
* present (defaulted when the server omits them) because shipped copy reads
|
|
43
|
-
* them unconditionally; every dimension added since is optional, so an older
|
|
44
|
-
* server simply leaves it absent and the renderer quotes the Starter cap.
|
|
45
|
-
*/
|
|
46
|
-
export interface PlanLockFixOptions {
|
|
47
|
-
removeMembersTo: number;
|
|
48
|
-
disconnectIntegrations: boolean;
|
|
49
|
-
disconnectIntegrationsTo?: number;
|
|
50
|
-
removeSecretsTo?: number;
|
|
51
|
-
deprovisionAgentsTo?: number;
|
|
52
|
-
}
|
|
31
|
+
export type PlanLimitReason = (typeof PLAN_LIMIT_REASONS)[number];
|
|
32
|
+
/** @deprecated US-040 — alias of {@link PlanLimitReason}. */
|
|
33
|
+
export type PlanLockReason = PlanLimitReason;
|
|
53
34
|
/** Optional member decoration for the notice ("7 of 5 members"). */
|
|
54
|
-
export interface
|
|
35
|
+
export interface PlanLimitMembers {
|
|
55
36
|
used: number;
|
|
56
37
|
limit: number;
|
|
57
38
|
}
|
|
58
|
-
|
|
39
|
+
/** @deprecated US-040 — alias of {@link PlanLimitMembers}. */
|
|
40
|
+
export type PlanLockMembers = PlanLimitMembers;
|
|
41
|
+
export interface PlanLimitFreeMonth {
|
|
42
|
+
eligible: boolean;
|
|
43
|
+
trialDays?: number;
|
|
44
|
+
url?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface PlanLimitStatus {
|
|
59
47
|
companySlug: string;
|
|
60
48
|
companyUid?: string;
|
|
61
|
-
|
|
62
|
-
|
|
49
|
+
/** True when any named dimension is over its cap. */
|
|
50
|
+
over: boolean;
|
|
51
|
+
reasons: PlanLimitReason[];
|
|
52
|
+
members?: PlanLimitMembers;
|
|
53
|
+
usages: Partial<Record<PlanLimitReason, PlanLimitMembers>>;
|
|
54
|
+
upgradeUrl: string;
|
|
55
|
+
freeMonth?: PlanLimitFreeMonth;
|
|
63
56
|
/**
|
|
64
57
|
* Resolved plan id, when the usage endpoint answered. UNKNOWN (absent) when
|
|
65
58
|
* it did not — surfaces that gate on "is this Starter?" must then stay
|
|
@@ -68,51 +61,53 @@ export interface PlanLockStatus {
|
|
|
68
61
|
plan?: "free" | "paid" | "enterprise";
|
|
69
62
|
checkedAt: string;
|
|
70
63
|
}
|
|
71
|
-
/**
|
|
64
|
+
/** @deprecated US-040 — alias of {@link PlanLimitStatus}. */
|
|
65
|
+
export type PlanLockStatus = PlanLimitStatus;
|
|
66
|
+
/** Starter member cap quoted when the server did not send a users.limit. */
|
|
72
67
|
export declare const STARTER_MEMBER_TARGET = 5;
|
|
73
68
|
/**
|
|
74
|
-
* Starter integration cap quoted when the server did not send
|
|
75
|
-
*
|
|
76
|
-
* (US-020 owner decision 11, 2026-09-17 — it was zero before that).
|
|
69
|
+
* Starter integration cap quoted when the server did not send a limit.
|
|
70
|
+
* One: Starter includes a single integration (US-020 owner decision 11).
|
|
77
71
|
*/
|
|
78
72
|
export declare const STARTER_INTEGRATION_TARGET = 1;
|
|
79
|
-
/** Starter secret cap quoted when the server did not send
|
|
73
|
+
/** Starter secret cap quoted when the server did not send a secrets.limit. */
|
|
80
74
|
export declare const STARTER_SECRET_TARGET = 10;
|
|
81
|
-
/** Starter agent cap quoted when the server did not send
|
|
75
|
+
/** Starter agent cap quoted when the server did not send an agents.limit. */
|
|
82
76
|
export declare const STARTER_AGENT_TARGET = 0;
|
|
83
77
|
/** Upgrade destination quoted when the server did not send one. */
|
|
84
78
|
export declare const DEFAULT_UPGRADE_URL = "https://hq.computer/billing";
|
|
85
|
-
/** The paid plan the
|
|
79
|
+
/** The paid plan the nag sends owners to. Copy lives in ONE place. */
|
|
86
80
|
export declare const WORKFORCE_PLAN_LABEL = "HQ Workforce ($500/mo)";
|
|
87
|
-
|
|
88
|
-
* Defensively parse a `planLock` payload. Anything malformed returns null —
|
|
89
|
-
* the caller then behaves exactly as if the server had sent nothing, which is
|
|
90
|
-
* "unknown", not "locked".
|
|
91
|
-
*/
|
|
92
|
-
export declare function parsePlanLock(value: unknown): PlanLock | null;
|
|
81
|
+
export declare function parseFreeMonth(value: unknown): PlanLimitFreeMonth | undefined;
|
|
93
82
|
/**
|
|
94
83
|
* Pick the membership row for `companySlug` (or `cmp_…` uid) out of a decoded
|
|
95
|
-
* `/membership/me` body
|
|
96
|
-
* `planLock` on it — is UNKNOWN, so this returns null rather than guessing.
|
|
84
|
+
* `/membership/me` body. No matching row is UNKNOWN. Does not read `planLock`.
|
|
97
85
|
*/
|
|
98
|
-
export declare function
|
|
99
|
-
lock: PlanLock;
|
|
86
|
+
export declare function selectCompanyMembership(body: unknown, companyRef: string): {
|
|
100
87
|
companyUid?: string;
|
|
101
88
|
} | null;
|
|
102
89
|
/** Parse the resolved plan id out of a usage-limits body. Absent → null. */
|
|
103
90
|
export declare function selectPlan(body: unknown): "free" | "paid" | "enterprise" | null;
|
|
104
91
|
/** Parse the `users` dimension out of a usage-limits body. Absent → null. */
|
|
105
|
-
export declare function selectMemberUsage(body: unknown):
|
|
92
|
+
export declare function selectMemberUsage(body: unknown): PlanLimitMembers | null;
|
|
93
|
+
/**
|
|
94
|
+
* Read over-limit dimensions from a usage-limits body. `planLimits` nested
|
|
95
|
+
* map is preferred when present; otherwise the top-level resource rows.
|
|
96
|
+
*/
|
|
97
|
+
export declare function selectOverReasons(body: unknown): PlanLimitReason[];
|
|
98
|
+
export declare function selectUsages(body: unknown): Partial<Record<PlanLimitReason, PlanLimitMembers>>;
|
|
106
99
|
/**
|
|
107
|
-
* Read the live
|
|
108
|
-
*
|
|
109
|
-
* answer
|
|
100
|
+
* Read the live nag for one company from usage-limits. `/membership/me` is
|
|
101
|
+
* used only to resolve slug → companyUid. Returns null when the server did
|
|
102
|
+
* not answer for this company — callers must then say nothing.
|
|
110
103
|
*/
|
|
111
|
-
export declare function
|
|
104
|
+
export declare function fetchPlanLimitStatus(token: string, companyRef: string, opts?: {
|
|
112
105
|
timeoutMs?: number;
|
|
113
|
-
}): Promise<
|
|
106
|
+
}): Promise<PlanLimitStatus | null>;
|
|
107
|
+
/** @deprecated US-040 — alias of {@link fetchPlanLimitStatus}. */
|
|
108
|
+
export declare const fetchPlanLockStatus: typeof fetchPlanLimitStatus;
|
|
114
109
|
/** Why the workspace is over, one clause per reason. */
|
|
115
|
-
export declare function reasonLabel(reason:
|
|
110
|
+
export declare function reasonLabel(reason: PlanLimitReason): string;
|
|
116
111
|
/**
|
|
117
112
|
* The one sentence every over-limit surface says about the two hard stops
|
|
118
113
|
* (US-033 §3.3). Written once so the CLI, the console and the emails cannot
|
|
@@ -124,22 +119,22 @@ export declare const HARD_STOP_SENTENCE: string;
|
|
|
124
119
|
* against the cap, and the ways out. Plain text — colour is applied by the
|
|
125
120
|
* caller so scripts capturing stdout get a clean block.
|
|
126
121
|
*
|
|
127
|
-
* Every line is derived from `
|
|
122
|
+
* Every line is derived from `status.reasons`. A workspace over on secrets is
|
|
128
123
|
* never told it has too many members, and an empty reason list (a server
|
|
129
124
|
* dimension this CLI does not know) renders a generic line rather than a claim
|
|
130
125
|
* about a dimension nobody measured.
|
|
131
126
|
*/
|
|
132
|
-
export declare function renderPlanLimitNotice(status:
|
|
127
|
+
export declare function renderPlanLimitNotice(status: PlanLimitStatus): string;
|
|
133
128
|
/**
|
|
134
129
|
* The one-line form injected on every turn while the workspace stays over.
|
|
135
130
|
* Kept to a single line on purpose — it repeats each turn.
|
|
136
131
|
*/
|
|
137
|
-
export declare function renderPlanLimitLine(status:
|
|
132
|
+
export declare function renderPlanLimitLine(status: PlanLimitStatus): string;
|
|
138
133
|
/**
|
|
139
134
|
* The `Plan: …` orientation line. Starter only: a paid or enterprise
|
|
140
135
|
* workspace — and an UNKNOWN plan — gets no line at all.
|
|
141
136
|
*/
|
|
142
|
-
export declare function renderPlanLine(status:
|
|
137
|
+
export declare function renderPlanLine(status: PlanLimitStatus): string | null;
|
|
143
138
|
/**
|
|
144
139
|
* Colourised block for interactive output. Yellow, not red: this is a nag, and
|
|
145
140
|
* an error colour would read as "HQ has stopped working", which is the exact
|