@indigoai-us/hq-cli 5.119.4 → 5.119.5
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 +16 -0
- package/dist/commands/agents.js +24 -1
- package/dist/lib/billing/plan-lock.d.ts +7 -0
- package/dist/lib/billing/plan-lock.js +19 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.119.5] — 2026-09-17
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- When a new Slack agent is waiting for a Socket Mode app-level token, `hq
|
|
10
|
+
agents status` now shows a link to create the token and a direct link to the
|
|
11
|
+
HQ form where it can be pasted. The same links are included in JSON output.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Starter now includes 1 integration instead of none, and the lock copy says
|
|
16
|
+
so. The notice reads "too many integrations", quotes "Integrations allowed
|
|
17
|
+
on Starter: 1", and tells you to "disconnect integrations until you are at 1
|
|
18
|
+
or fewer"; the per-turn line reads "over its 1-integration limit". Nothing in
|
|
19
|
+
the CLI says Starter has no integrations any more.
|
|
20
|
+
|
|
5
21
|
## [5.119.4] — 2026-09-17
|
|
6
22
|
|
|
7
23
|
### Fixed
|
package/dist/commands/agents.js
CHANGED
|
@@ -445,6 +445,26 @@ function currentDeviceSignInAction(status) {
|
|
|
445
445
|
}
|
|
446
446
|
function pendingSlackAction(status) {
|
|
447
447
|
const agent = recordValue(status.agent);
|
|
448
|
+
const configuredSlack = recordValue(recordValue(agent?.channels)?.slack);
|
|
449
|
+
const appId = nonEmptyString(configuredSlack?.appId);
|
|
450
|
+
const agentUid = nonEmptyString(agent?.uid);
|
|
451
|
+
const companyUid = nonEmptyString(agent?.companyUid);
|
|
452
|
+
const tokenPage = safeActionUrl(configuredSlack?.appTokenPendingUrl);
|
|
453
|
+
if (tokenPage &&
|
|
454
|
+
appId && /^A[A-Z0-9]+$/.test(appId) &&
|
|
455
|
+
new URL(tokenPage).hostname === "api.slack.com" &&
|
|
456
|
+
agentUid && AGENT_UID_PATTERN.test(agentUid) &&
|
|
457
|
+
companyUid && /^cmp_[A-Za-z0-9_-]+$/.test(companyUid)) {
|
|
458
|
+
return {
|
|
459
|
+
type: "slack-app-token",
|
|
460
|
+
title: `Finish ${nonEmptyString(agent?.name) ?? "the agent"}'s Slack connection`,
|
|
461
|
+
summary: "connect it to Slack",
|
|
462
|
+
instruction: "Create an app-level token with the connections:write scope, then paste it into HQ. HQ verifies the token and resumes setup; if Slack asks you to install the app, follow the install link shown there.",
|
|
463
|
+
url: `https://api.slack.com/apps/${appId}/general`,
|
|
464
|
+
urlLabel: "Get token",
|
|
465
|
+
pasteUrl: `https://hq.computer/companies/${encodeURIComponent(companyUid)}/agents?setup=${encodeURIComponent(agentUid)}`,
|
|
466
|
+
};
|
|
467
|
+
}
|
|
448
468
|
const diagnostics = recordValue(agent?.channelDiagnostics);
|
|
449
469
|
const slack = recordValue(diagnostics?.slack);
|
|
450
470
|
const url = safeActionUrl(slack?.pendingInstallUrl);
|
|
@@ -483,11 +503,12 @@ function pendingOperatorActions(status) {
|
|
|
483
503
|
].filter((action) => action !== null);
|
|
484
504
|
}
|
|
485
505
|
function pendingActionsJson(actions) {
|
|
486
|
-
return actions.map(({ type, title, instruction, url, code }) => ({
|
|
506
|
+
return actions.map(({ type, title, instruction, url, pasteUrl, code }) => ({
|
|
487
507
|
type,
|
|
488
508
|
title,
|
|
489
509
|
instruction,
|
|
490
510
|
...(url ? { url } : {}),
|
|
511
|
+
...(pasteUrl ? { pasteUrl } : {}),
|
|
491
512
|
...(code ? { code } : {}),
|
|
492
513
|
}));
|
|
493
514
|
}
|
|
@@ -514,6 +535,8 @@ function printPendingOperatorActions(slug, actions) {
|
|
|
514
535
|
console.log(action.instruction);
|
|
515
536
|
if (action.url)
|
|
516
537
|
console.log(chalk.cyan(`${action.urlLabel ?? "Open"}: ${action.url}`));
|
|
538
|
+
if (action.pasteUrl)
|
|
539
|
+
console.log(chalk.cyan(`Paste token: ${action.pasteUrl}`));
|
|
517
540
|
if (action.code)
|
|
518
541
|
console.log(chalk.bold(`Code: ${action.code}`));
|
|
519
542
|
}
|
|
@@ -41,6 +41,7 @@ export interface PlanLock {
|
|
|
41
41
|
export interface PlanLockFixOptions {
|
|
42
42
|
removeMembersTo: number;
|
|
43
43
|
disconnectIntegrations: boolean;
|
|
44
|
+
disconnectIntegrationsTo?: number;
|
|
44
45
|
removeSecretsTo?: number;
|
|
45
46
|
deprovisionAgentsTo?: number;
|
|
46
47
|
}
|
|
@@ -64,6 +65,12 @@ export interface PlanLockStatus {
|
|
|
64
65
|
}
|
|
65
66
|
/** Starter member cap quoted when the server did not send `removeMembersTo`. */
|
|
66
67
|
export declare const STARTER_MEMBER_TARGET = 5;
|
|
68
|
+
/**
|
|
69
|
+
* Starter integration cap quoted when the server did not send
|
|
70
|
+
* `disconnectIntegrationsTo`. One: Starter includes a single integration
|
|
71
|
+
* (US-020 owner decision 11, 2026-09-17 — it was zero before that).
|
|
72
|
+
*/
|
|
73
|
+
export declare const STARTER_INTEGRATION_TARGET = 1;
|
|
67
74
|
/** Starter secret cap quoted when the server did not send `removeSecretsTo`. */
|
|
68
75
|
export declare const STARTER_SECRET_TARGET = 10;
|
|
69
76
|
/** Starter agent cap quoted when the server did not send `deprovisionAgentsTo`. */
|
|
@@ -36,6 +36,12 @@ function isPlanLockReason(value) {
|
|
|
36
36
|
}
|
|
37
37
|
/** Starter member cap quoted when the server did not send `removeMembersTo`. */
|
|
38
38
|
export const STARTER_MEMBER_TARGET = 5;
|
|
39
|
+
/**
|
|
40
|
+
* Starter integration cap quoted when the server did not send
|
|
41
|
+
* `disconnectIntegrationsTo`. One: Starter includes a single integration
|
|
42
|
+
* (US-020 owner decision 11, 2026-09-17 — it was zero before that).
|
|
43
|
+
*/
|
|
44
|
+
export const STARTER_INTEGRATION_TARGET = 1;
|
|
39
45
|
/** Starter secret cap quoted when the server did not send `removeSecretsTo`. */
|
|
40
46
|
export const STARTER_SECRET_TARGET = 10;
|
|
41
47
|
/** Starter agent cap quoted when the server did not send `deprovisionAgentsTo`. */
|
|
@@ -73,6 +79,7 @@ export function parsePlanLock(value) {
|
|
|
73
79
|
}
|
|
74
80
|
const fix = asRecord(rec.fixOptions);
|
|
75
81
|
const removeMembersTo = finiteNumber(fix?.removeMembersTo) ?? STARTER_MEMBER_TARGET;
|
|
82
|
+
const disconnectIntegrationsTo = finiteNumber(fix?.disconnectIntegrationsTo);
|
|
76
83
|
const removeSecretsTo = finiteNumber(fix?.removeSecretsTo);
|
|
77
84
|
const deprovisionAgentsTo = finiteNumber(fix?.deprovisionAgentsTo);
|
|
78
85
|
const fixOptions = {
|
|
@@ -81,6 +88,9 @@ export function parsePlanLock(value) {
|
|
|
81
88
|
};
|
|
82
89
|
// Absent stays absent: an omitted remedy target is UNKNOWN, and the renderer
|
|
83
90
|
// quotes the published Starter cap rather than inventing a server answer.
|
|
91
|
+
if (disconnectIntegrationsTo !== null) {
|
|
92
|
+
fixOptions.disconnectIntegrationsTo = disconnectIntegrationsTo;
|
|
93
|
+
}
|
|
84
94
|
if (removeSecretsTo !== null)
|
|
85
95
|
fixOptions.removeSecretsTo = removeSecretsTo;
|
|
86
96
|
if (deprovisionAgentsTo !== null) {
|
|
@@ -200,13 +210,16 @@ export function reasonLabel(reason) {
|
|
|
200
210
|
case "users":
|
|
201
211
|
return "too many members";
|
|
202
212
|
case "integrations":
|
|
203
|
-
return "
|
|
213
|
+
return "too many integrations";
|
|
204
214
|
case "secrets":
|
|
205
215
|
return "too many secrets";
|
|
206
216
|
case "agents":
|
|
207
217
|
return "agents are not included on Starter";
|
|
208
218
|
}
|
|
209
219
|
}
|
|
220
|
+
function integrationTarget(lock) {
|
|
221
|
+
return lock.fixOptions.disconnectIntegrationsTo ?? STARTER_INTEGRATION_TARGET;
|
|
222
|
+
}
|
|
210
223
|
function secretTarget(lock) {
|
|
211
224
|
return lock.fixOptions.removeSecretsTo ?? STARTER_SECRET_TARGET;
|
|
212
225
|
}
|
|
@@ -219,7 +232,7 @@ function reasonRemedy(reason, lock) {
|
|
|
219
232
|
case "users":
|
|
220
233
|
return `remove members until you are at ${lock.fixOptions.removeMembersTo} or fewer`;
|
|
221
234
|
case "integrations":
|
|
222
|
-
return
|
|
235
|
+
return `disconnect integrations until you are at ${integrationTarget(lock)} or fewer`;
|
|
223
236
|
case "secrets":
|
|
224
237
|
return `delete secrets until you are at ${secretTarget(lock)} or fewer`;
|
|
225
238
|
case "agents": {
|
|
@@ -241,7 +254,7 @@ function reasonDetail(reason, status) {
|
|
|
241
254
|
: `over its ${target}-member limit`;
|
|
242
255
|
}
|
|
243
256
|
case "integrations":
|
|
244
|
-
return
|
|
257
|
+
return `over its ${integrationTarget(status.lock)}-integration limit`;
|
|
245
258
|
case "secrets":
|
|
246
259
|
return `over its ${secretTarget(status.lock)}-secret limit`;
|
|
247
260
|
case "agents":
|
|
@@ -275,6 +288,9 @@ export function renderPlanLockNotice(status) {
|
|
|
275
288
|
? ` Members: ${members.used} of ${target}.`
|
|
276
289
|
: ` Members allowed on Starter: ${target}.`);
|
|
277
290
|
}
|
|
291
|
+
if (lock.reasons.includes("integrations")) {
|
|
292
|
+
lines.push(` Integrations allowed on Starter: ${integrationTarget(lock)}.`);
|
|
293
|
+
}
|
|
278
294
|
if (lock.reasons.includes("secrets")) {
|
|
279
295
|
lines.push(` Secrets allowed on Starter: ${secretTarget(lock)}.`);
|
|
280
296
|
}
|