@indigoai-us/hq-cli 5.61.0 → 5.62.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.
Files changed (80) hide show
  1. package/dist/commands/agents.d.ts +109 -0
  2. package/dist/commands/agents.js +385 -0
  3. package/dist/commands/db-migrate.d.ts +6 -0
  4. package/dist/commands/db-migrate.js +42 -0
  5. package/dist/commands/db-provision.d.ts +15 -0
  6. package/dist/commands/db-provision.js +78 -0
  7. package/dist/commands/db-sql.d.ts +9 -0
  8. package/dist/commands/db-sql.js +81 -0
  9. package/dist/commands/db-status.d.ts +7 -0
  10. package/dist/commands/db-status.js +70 -0
  11. package/dist/commands/db.d.ts +9 -0
  12. package/dist/commands/db.js +23 -0
  13. package/dist/commands/integrations.d.ts +78 -0
  14. package/dist/commands/integrations.js +309 -0
  15. package/dist/commands/members.js +4 -4
  16. package/dist/commands/outposts.d.ts +60 -0
  17. package/dist/commands/outposts.js +255 -0
  18. package/dist/commands/secrets.d.ts +8 -0
  19. package/dist/commands/secrets.js +23 -8
  20. package/dist/commands/skill.d.ts +153 -0
  21. package/dist/commands/skill.js +593 -0
  22. package/dist/commands/workers.d.ts +48 -0
  23. package/dist/commands/workers.js +229 -0
  24. package/dist/lib/db/control-plane.d.ts +45 -0
  25. package/dist/lib/db/control-plane.js +81 -0
  26. package/dist/lib/db/local.d.ts +49 -0
  27. package/dist/lib/db/local.js +106 -0
  28. package/dist/lib/db/migrate.d.ts +41 -0
  29. package/dist/lib/db/migrate.js +104 -0
  30. package/dist/lib/db/paths.d.ts +56 -0
  31. package/dist/lib/db/paths.js +103 -0
  32. package/dist/lib/db/remote-engine.d.ts +58 -0
  33. package/dist/lib/db/remote-engine.js +90 -0
  34. package/dist/lib/db/remote-sql.d.ts +22 -0
  35. package/dist/lib/db/remote-sql.js +39 -0
  36. package/dist/lib/db/sql.d.ts +49 -0
  37. package/dist/lib/db/sql.js +132 -0
  38. package/dist/main.js +27 -2
  39. package/dist/utils/cognito-session.js +3 -3
  40. package/dist/utils/sandbox-runner-client.js +3 -3
  41. package/package.json +9 -1
  42. package/pnpm-workspace.yaml +2 -0
  43. package/src/commands/agents.test.ts +297 -0
  44. package/src/commands/agents.ts +561 -0
  45. package/src/commands/db-migrate.ts +55 -0
  46. package/src/commands/db-provision.ts +102 -0
  47. package/src/commands/db-sql.ts +124 -0
  48. package/src/commands/db-status.ts +100 -0
  49. package/src/commands/db.ts +26 -0
  50. package/src/commands/integrations.test.ts +284 -0
  51. package/src/commands/integrations.ts +438 -0
  52. package/src/commands/members.ts +2 -2
  53. package/src/commands/outposts.test.ts +177 -0
  54. package/src/commands/outposts.ts +338 -0
  55. package/src/commands/secrets.parse-destination.test.ts +38 -0
  56. package/src/commands/secrets.test.ts +24 -0
  57. package/src/commands/secrets.ts +30 -10
  58. package/src/commands/skill.test.ts +770 -0
  59. package/src/commands/skill.ts +796 -0
  60. package/src/commands/workers.test.ts +158 -0
  61. package/src/commands/workers.ts +298 -0
  62. package/src/lib/db/control-plane.test.ts +59 -0
  63. package/src/lib/db/control-plane.ts +113 -0
  64. package/src/lib/db/local.test.ts +81 -0
  65. package/src/lib/db/local.ts +148 -0
  66. package/src/lib/db/migrate.test.ts +133 -0
  67. package/src/lib/db/migrate.ts +137 -0
  68. package/src/lib/db/paths.test.ts +112 -0
  69. package/src/lib/db/paths.ts +128 -0
  70. package/src/lib/db/remote-engine.test.ts +44 -0
  71. package/src/lib/db/remote-engine.ts +148 -0
  72. package/src/lib/db/remote-sql.test.ts +32 -0
  73. package/src/lib/db/remote-sql.ts +62 -0
  74. package/src/lib/db/sql.test.ts +106 -0
  75. package/src/lib/db/sql.ts +192 -0
  76. package/src/main.ts +31 -0
  77. package/src/utils/cognito-session.ts +1 -1
  78. package/src/utils/sandbox-runner-client.ts +1 -1
  79. package/test/commands/db-tenant-isolation.test.ts +94 -0
  80. package/test/commands/db.test.ts +85 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * `hq agents` — manage a company's cloud (fleet) agents from the terminal
3
+ * instead of the web console. Mirrors the console's `AgentsClient`
4
+ * (hq-console `src/lib/agents-client.ts`), targeting the hq-pro `/v1/agents`
5
+ * control plane on `DEFAULT_VAULT_API_URL` via the shared `vaultApiFetch`
6
+ * helper. No new HTTP client, no console-SDK import — same auth + company
7
+ * resolution stack as `members.ts`.
8
+ *
9
+ * Subcommands:
10
+ * hq agents list — roster for the company
11
+ * hq agents status <uid> — setup state + runtime detail
12
+ * hq agents rename <uid> <name> — set the agent's display name
13
+ * hq agents set <uid> [...] — patch profile (name/title/description)
14
+ * hq agents config <uid> [...] — patch runtime config (model/effort/tier)
15
+ * hq agents start|stop <uid> — EC2 start/stop
16
+ * hq agents retry <uid> — resume setup from first non-done step
17
+ * hq agents rm <uid> --yes — deprovision (destructive; flag-guarded)
18
+ *
19
+ * Agents are company-scoped. `--company <slug>` may sit on the group
20
+ * (`hq agents --company acme list`) or on a subcommand
21
+ * (`hq agents list --company acme`); when omitted, resolution falls back to
22
+ * the caller's single active membership (same as `members.ts`).
23
+ */
24
+ import { Command } from "commander";
25
+ /** Reasoning-effort values hq-pro accepts on `runtime-config`. */
26
+ export declare const VALID_EFFORTS: Set<string>;
27
+ /** Service-tier (speed) values hq-pro accepts on `runtime-config`. */
28
+ export declare const VALID_TIERS: Set<string>;
29
+ /**
30
+ * A non-2xx from the `/v1/agents` control plane. Carries the HTTP status and
31
+ * the registry error `code` (when present) so callers can branch — notably a
32
+ * 404 on `list`, which hq-pro returns for a company that has the agents
33
+ * feature flag OFF (`src/agents/feature-flag.ts`).
34
+ */
35
+ export declare class AgentsHttpError extends Error {
36
+ status: number;
37
+ code?: string;
38
+ constructor(status: number, message: string, code?: string);
39
+ }
40
+ /** Roster row from `GET /v1/agents` — a superset is returned; we keep what we render. */
41
+ export interface CompanyAgentView {
42
+ uid: string;
43
+ name: string;
44
+ slug: string;
45
+ companyUid: string;
46
+ entityStatus?: string;
47
+ agentStatus?: string;
48
+ setupPhase?: string;
49
+ provider?: string;
50
+ codexModel?: string;
51
+ codexReasoningEffort?: string;
52
+ codexServiceTier?: string;
53
+ profile?: {
54
+ displayName?: string;
55
+ title?: string;
56
+ description?: string;
57
+ };
58
+ [key: string]: unknown;
59
+ }
60
+ export interface ProfilePatch {
61
+ displayName?: string;
62
+ title?: string;
63
+ description?: string;
64
+ }
65
+ export interface RuntimeConfigPatch {
66
+ codexModel?: string;
67
+ codexReasoningEffort?: string;
68
+ codexServiceTier?: string;
69
+ }
70
+ /**
71
+ * Authenticated JSON round-trip against the agents control plane. Throws
72
+ * `AgentsHttpError` on any non-2xx (never swallows — hq-never-swallow-errors),
73
+ * decoding hq-pro's `{ error | message, code }` envelope for the reason.
74
+ */
75
+ export declare function agentsRequest<T>(opts: {
76
+ token: string;
77
+ path: string;
78
+ method?: string;
79
+ body?: Record<string, unknown>;
80
+ query?: Record<string, string>;
81
+ }): Promise<T>;
82
+ export declare function listAgents(token: string, companyUid: string): Promise<CompanyAgentView[]>;
83
+ export declare function getAgentStatus(token: string, agentUid: string): Promise<Record<string, unknown>>;
84
+ export declare function patchAgentProfile(token: string, agentUid: string, patch: ProfilePatch): Promise<{
85
+ uid: string;
86
+ profile: ProfilePatch;
87
+ slackUpdated: boolean;
88
+ }>;
89
+ export declare function patchAgentRuntimeConfig(token: string, agentUid: string, patch: RuntimeConfigPatch): Promise<{
90
+ uid: string;
91
+ codexModel?: string;
92
+ codexReasoningEffort?: string;
93
+ codexServiceTier?: string;
94
+ applied: boolean;
95
+ }>;
96
+ export declare function startStopAgent(token: string, agentUid: string, action: "start" | "stop"): Promise<{
97
+ uid: string;
98
+ runtime?: Record<string, unknown>;
99
+ }>;
100
+ export declare function retryAgent(token: string, agentUid: string): Promise<Record<string, unknown>>;
101
+ export declare function deprovisionAgent(token: string, agentUid: string): Promise<{
102
+ uid: string;
103
+ setupState?: string;
104
+ terminal?: boolean;
105
+ }>;
106
+ /** Human-readable "hot-applied to the running box" vs "saved for next launch". */
107
+ export declare function appliedHint(applied: boolean): string;
108
+ export declare function registerAgentsCommand(program: Command): void;
109
+ //# sourceMappingURL=agents.d.ts.map
@@ -0,0 +1,385 @@
1
+ /**
2
+ * `hq agents` — manage a company's cloud (fleet) agents from the terminal
3
+ * instead of the web console. Mirrors the console's `AgentsClient`
4
+ * (hq-console `src/lib/agents-client.ts`), targeting the hq-pro `/v1/agents`
5
+ * control plane on `DEFAULT_VAULT_API_URL` via the shared `vaultApiFetch`
6
+ * helper. No new HTTP client, no console-SDK import — same auth + company
7
+ * resolution stack as `members.ts`.
8
+ *
9
+ * Subcommands:
10
+ * hq agents list — roster for the company
11
+ * hq agents status <uid> — setup state + runtime detail
12
+ * hq agents rename <uid> <name> — set the agent's display name
13
+ * hq agents set <uid> [...] — patch profile (name/title/description)
14
+ * hq agents config <uid> [...] — patch runtime config (model/effort/tier)
15
+ * hq agents start|stop <uid> — EC2 start/stop
16
+ * hq agents retry <uid> — resume setup from first non-done step
17
+ * hq agents rm <uid> --yes — deprovision (destructive; flag-guarded)
18
+ *
19
+ * Agents are company-scoped. `--company <slug>` may sit on the group
20
+ * (`hq agents --company acme list`) or on a subcommand
21
+ * (`hq agents list --company acme`); when omitted, resolution falls back to
22
+ * the caller's single active membership (same as `members.ts`).
23
+ */
24
+
25
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8a374059-a137-5cce-94ad-9e2647fc37c5")}catch(e){}}();
26
+ import chalk from "chalk";
27
+ import { ensureCognitoToken } from "../utils/cognito-session.js";
28
+ import { vaultApiFetch, getCompanyUid } from "../utils/vault-api.js";
29
+ /** Reasoning-effort values hq-pro accepts on `runtime-config`. */
30
+ export const VALID_EFFORTS = new Set([
31
+ "minimal",
32
+ "low",
33
+ "medium",
34
+ "high",
35
+ "xhigh",
36
+ ]);
37
+ /** Service-tier (speed) values hq-pro accepts on `runtime-config`. */
38
+ export const VALID_TIERS = new Set(["default", "priority"]);
39
+ /**
40
+ * A non-2xx from the `/v1/agents` control plane. Carries the HTTP status and
41
+ * the registry error `code` (when present) so callers can branch — notably a
42
+ * 404 on `list`, which hq-pro returns for a company that has the agents
43
+ * feature flag OFF (`src/agents/feature-flag.ts`).
44
+ */
45
+ export class AgentsHttpError extends Error {
46
+ status;
47
+ code;
48
+ constructor(status, message, code) {
49
+ super(message);
50
+ this.name = "AgentsHttpError";
51
+ this.status = status;
52
+ this.code = code;
53
+ }
54
+ }
55
+ /**
56
+ * Authenticated JSON round-trip against the agents control plane. Throws
57
+ * `AgentsHttpError` on any non-2xx (never swallows — hq-never-swallow-errors),
58
+ * decoding hq-pro's `{ error | message, code }` envelope for the reason.
59
+ */
60
+ export async function agentsRequest(opts) {
61
+ const res = await vaultApiFetch(opts);
62
+ if (!res.ok) {
63
+ const body = (await res.json().catch(() => ({})));
64
+ throw new AgentsHttpError(res.status, body.error ?? body.message ?? res.statusText, body.code);
65
+ }
66
+ return (await res.json());
67
+ }
68
+ export async function listAgents(token, companyUid) {
69
+ const data = await agentsRequest({
70
+ token,
71
+ path: "/v1/agents",
72
+ query: { companyUid },
73
+ });
74
+ return data.agents ?? [];
75
+ }
76
+ export async function getAgentStatus(token, agentUid) {
77
+ return agentsRequest({
78
+ token,
79
+ path: `/v1/agents/${encodeURIComponent(agentUid)}/status`,
80
+ });
81
+ }
82
+ export async function patchAgentProfile(token, agentUid, patch) {
83
+ return agentsRequest({
84
+ token,
85
+ path: `/v1/agents/${encodeURIComponent(agentUid)}/profile`,
86
+ method: "PATCH",
87
+ body: patch,
88
+ });
89
+ }
90
+ export async function patchAgentRuntimeConfig(token, agentUid, patch) {
91
+ return agentsRequest({
92
+ token,
93
+ path: `/v1/agents/${encodeURIComponent(agentUid)}/runtime-config`,
94
+ method: "PATCH",
95
+ body: patch,
96
+ });
97
+ }
98
+ export async function startStopAgent(token, agentUid, action) {
99
+ return agentsRequest({
100
+ token,
101
+ path: `/v1/agents/${encodeURIComponent(agentUid)}/${action}`,
102
+ method: "POST",
103
+ });
104
+ }
105
+ export async function retryAgent(token, agentUid) {
106
+ return agentsRequest({
107
+ token,
108
+ path: `/v1/agents/${encodeURIComponent(agentUid)}/retry`,
109
+ method: "POST",
110
+ });
111
+ }
112
+ export async function deprovisionAgent(token, agentUid) {
113
+ return agentsRequest({
114
+ token,
115
+ path: `/v1/agents/${encodeURIComponent(agentUid)}`,
116
+ method: "DELETE",
117
+ });
118
+ }
119
+ /** Human-readable "hot-applied to the running box" vs "saved for next launch". */
120
+ export function appliedHint(applied) {
121
+ return applied
122
+ ? "applied to the running box now"
123
+ : "saved — takes effect on the agent's next launch";
124
+ }
125
+ // ---------------------------------------------------------------------------
126
+ // Command registration
127
+ // ---------------------------------------------------------------------------
128
+ function fail(err) {
129
+ if (err instanceof AgentsHttpError) {
130
+ console.error(chalk.red(err.message));
131
+ }
132
+ else {
133
+ console.error(chalk.red("Error:"), err instanceof Error ? err.message : String(err));
134
+ }
135
+ process.exit(1);
136
+ }
137
+ export function registerAgentsCommand(program) {
138
+ const agents = program
139
+ .command("agents")
140
+ .description("Manage a company's cloud (fleet) agents")
141
+ .option("--company <slug>", "Company slug (resolves to companyUid)");
142
+ // `--company` may live on the group or the subcommand; the subcommand value
143
+ // wins so `hq agents list --company acme` works as well as
144
+ // `hq agents --company acme list`.
145
+ const companyOf = (sub) => sub.opts().company ??
146
+ agents.opts().company;
147
+ agents
148
+ .command("list")
149
+ .description("List the company's agents")
150
+ .option("--company <slug>", "Company slug (resolves to companyUid)")
151
+ .option("--json", "Emit raw JSON")
152
+ .action(async function (opts) {
153
+ try {
154
+ const token = await ensureCognitoToken();
155
+ const companyUid = await getCompanyUid(token, companyOf(this));
156
+ let roster;
157
+ try {
158
+ roster = await listAgents(token, companyUid);
159
+ }
160
+ catch (err) {
161
+ // A 404 here means the company doesn't have the agents feature
162
+ // enabled (hq-pro returns 404 on every /v1/agents route for a
163
+ // flag-OFF company) — surface that plainly rather than a raw error.
164
+ if (err instanceof AgentsHttpError && err.status === 404) {
165
+ console.log(chalk.gray("No cloud agents are available for this company (the agents feature isn't enabled here)."));
166
+ return;
167
+ }
168
+ throw err;
169
+ }
170
+ if (opts.json) {
171
+ process.stdout.write(JSON.stringify(roster, null, 2) + "\n");
172
+ return;
173
+ }
174
+ if (roster.length === 0) {
175
+ console.log(chalk.gray("No agents found for this company."));
176
+ return;
177
+ }
178
+ const nameW = Math.max(4, ...roster.map((a) => (a.name ?? "").length));
179
+ const slugW = Math.max(4, ...roster.map((a) => (a.slug ?? "").length));
180
+ const statusW = Math.max(6, ...roster.map((a) => (a.agentStatus ?? "").length));
181
+ const modelW = Math.max(5, ...roster.map((a) => (a.codexModel ?? "").length));
182
+ console.log(chalk.bold([
183
+ "NAME".padEnd(nameW),
184
+ "SLUG".padEnd(slugW),
185
+ "STATUS".padEnd(statusW),
186
+ "MODEL".padEnd(modelW),
187
+ "UID",
188
+ ].join(" ")));
189
+ for (const a of roster) {
190
+ console.log([
191
+ (a.name ?? "").padEnd(nameW),
192
+ (a.slug ?? "").padEnd(slugW),
193
+ (a.agentStatus ?? "").padEnd(statusW),
194
+ (a.codexModel ?? "").padEnd(modelW),
195
+ a.uid,
196
+ ].join(" "));
197
+ }
198
+ }
199
+ catch (err) {
200
+ fail(err);
201
+ }
202
+ });
203
+ agents
204
+ .command("status <agentUid>")
205
+ .description("Show an agent's setup state and runtime detail")
206
+ .option("--company <slug>", "Company slug (resolves to companyUid)")
207
+ .option("--json", "Emit raw JSON")
208
+ .action(async function (agentUid, opts) {
209
+ try {
210
+ const token = await ensureCognitoToken();
211
+ const status = await getAgentStatus(token, agentUid);
212
+ if (opts.json) {
213
+ process.stdout.write(JSON.stringify(status, null, 2) + "\n");
214
+ return;
215
+ }
216
+ // Pretty but faithful: dump the top-level fields as key: value.
217
+ for (const [k, v] of Object.entries(status)) {
218
+ const rendered = v && typeof v === "object" ? JSON.stringify(v) : String(v);
219
+ console.log(`${chalk.bold(k)}: ${rendered}`);
220
+ }
221
+ }
222
+ catch (err) {
223
+ fail(err);
224
+ }
225
+ });
226
+ agents
227
+ .command("rename <agentUid> <name>")
228
+ .description("Set an agent's display name")
229
+ .option("--company <slug>", "Company slug (resolves to companyUid)")
230
+ .action(async function (agentUid, name) {
231
+ try {
232
+ const token = await ensureCognitoToken();
233
+ const result = await patchAgentProfile(token, agentUid, {
234
+ displayName: name,
235
+ });
236
+ console.log(chalk.green(`Renamed agent ${agentUid} to "${name}"`));
237
+ if (result.slackUpdated) {
238
+ console.log(chalk.dim("Propagated to the agent's live Slack app."));
239
+ }
240
+ }
241
+ catch (err) {
242
+ fail(err);
243
+ }
244
+ });
245
+ agents
246
+ .command("set <agentUid>")
247
+ .description("Update an agent's profile (name / title / description)")
248
+ .option("--company <slug>", "Company slug (resolves to companyUid)")
249
+ .option("--name <displayName>", "Display name")
250
+ .option("--title <title>", 'Org-chart job title (e.g. "Chief of Staff")')
251
+ .option("--description <text>", "Short description / bio")
252
+ .option("--json", "Emit raw JSON")
253
+ .action(async function (agentUid, opts) {
254
+ try {
255
+ const patch = {};
256
+ if (opts.name !== undefined)
257
+ patch.displayName = opts.name;
258
+ if (opts.title !== undefined)
259
+ patch.title = opts.title;
260
+ if (opts.description !== undefined)
261
+ patch.description = opts.description;
262
+ if (Object.keys(patch).length === 0) {
263
+ console.error(chalk.red("Nothing to set. Pass at least one of --name, --title, --description."));
264
+ process.exit(1);
265
+ }
266
+ const token = await ensureCognitoToken();
267
+ const result = await patchAgentProfile(token, agentUid, patch);
268
+ if (opts.json) {
269
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
270
+ return;
271
+ }
272
+ console.log(chalk.green(`Updated profile for agent ${agentUid}.`));
273
+ if (result.slackUpdated) {
274
+ console.log(chalk.dim("Propagated to the agent's live Slack app."));
275
+ }
276
+ }
277
+ catch (err) {
278
+ fail(err);
279
+ }
280
+ });
281
+ agents
282
+ .command("config <agentUid>")
283
+ .description("Update an agent's runtime config (model / reasoning effort / service tier)")
284
+ .option("--company <slug>", "Company slug (resolves to companyUid)")
285
+ .option("--model <model>", "Codex model id")
286
+ .option("--effort <effort>", "Reasoning effort: minimal | low | medium | high | xhigh")
287
+ .option("--tier <tier>", "Service tier (speed): default | priority")
288
+ .option("--json", "Emit raw JSON")
289
+ .action(async function (agentUid, opts) {
290
+ try {
291
+ const patch = {};
292
+ if (opts.model !== undefined)
293
+ patch.codexModel = opts.model;
294
+ if (opts.effort !== undefined) {
295
+ const effort = opts.effort.trim().toLowerCase();
296
+ if (!VALID_EFFORTS.has(effort)) {
297
+ console.error(chalk.red(`Invalid --effort '${opts.effort}': must be one of minimal, low, medium, high, xhigh`));
298
+ process.exit(1);
299
+ }
300
+ patch.codexReasoningEffort = effort;
301
+ }
302
+ if (opts.tier !== undefined) {
303
+ const tier = opts.tier.trim().toLowerCase();
304
+ if (!VALID_TIERS.has(tier)) {
305
+ console.error(chalk.red(`Invalid --tier '${opts.tier}': must be one of default, priority`));
306
+ process.exit(1);
307
+ }
308
+ patch.codexServiceTier = tier;
309
+ }
310
+ if (Object.keys(patch).length === 0) {
311
+ console.error(chalk.red("Nothing to change. Pass at least one of --model, --effort, --tier."));
312
+ process.exit(1);
313
+ }
314
+ const token = await ensureCognitoToken();
315
+ const result = await patchAgentRuntimeConfig(token, agentUid, patch);
316
+ if (opts.json) {
317
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
318
+ return;
319
+ }
320
+ console.log(chalk.green(`Updated runtime config for agent ${agentUid} — ${appliedHint(result.applied)}.`));
321
+ }
322
+ catch (err) {
323
+ fail(err);
324
+ }
325
+ });
326
+ for (const action of ["start", "stop"]) {
327
+ agents
328
+ .command(`${action} <agentUid>`)
329
+ .description(`${action === "start" ? "Start" : "Stop"} an agent's box`)
330
+ .option("--company <slug>", "Company slug (resolves to companyUid)")
331
+ .action(async function (agentUid) {
332
+ try {
333
+ const token = await ensureCognitoToken();
334
+ await startStopAgent(token, agentUid, action);
335
+ console.log(chalk.green(`${action === "start" ? "Started" : "Stopped"} agent ${agentUid}.`));
336
+ }
337
+ catch (err) {
338
+ fail(err);
339
+ }
340
+ });
341
+ }
342
+ agents
343
+ .command("retry <agentUid>")
344
+ .description("Resume an agent's setup from the first non-done step")
345
+ .option("--company <slug>", "Company slug (resolves to companyUid)")
346
+ .action(async function (agentUid) {
347
+ try {
348
+ const token = await ensureCognitoToken();
349
+ await retryAgent(token, agentUid);
350
+ console.log(chalk.green(`Retry queued for agent ${agentUid}.`));
351
+ }
352
+ catch (err) {
353
+ fail(err);
354
+ }
355
+ });
356
+ agents
357
+ .command("rm <agentUid>")
358
+ .alias("delete")
359
+ .description("Deprovision (permanently tear down) an agent")
360
+ .option("--company <slug>", "Company slug (resolves to companyUid)")
361
+ .option("--yes", "Confirm the irreversible teardown (required)")
362
+ .action(async function (agentUid, opts) {
363
+ if (!opts.yes) {
364
+ console.error(chalk.yellow(`This will permanently deprovision agent ${agentUid} and tear down its ` +
365
+ `cloud resources. This cannot be undone.\n` +
366
+ `Re-run with --yes to confirm: hq agents rm ${agentUid} --yes`));
367
+ process.exit(1);
368
+ }
369
+ try {
370
+ const token = await ensureCognitoToken();
371
+ const result = await deprovisionAgent(token, agentUid);
372
+ if (result.terminal === false) {
373
+ console.log(chalk.yellow(`Deprovision in progress for agent ${agentUid} (not yet fully torn down — re-run to continue).`));
374
+ }
375
+ else {
376
+ console.log(chalk.green(`Deprovisioned agent ${agentUid}.`));
377
+ }
378
+ }
379
+ catch (err) {
380
+ fail(err);
381
+ }
382
+ });
383
+ }
384
+ //# sourceMappingURL=agents.js.map
385
+ //# debugId=8a374059-a137-5cce-94ad-9e2647fc37c5
@@ -0,0 +1,6 @@
1
+ /**
2
+ * hq db migrate — apply vault text migrations to local SQLite (US-005).
3
+ */
4
+ import { Command } from "commander";
5
+ export declare function registerDbMigrateCommand(db: Command): void;
6
+ //# sourceMappingURL=db-migrate.d.ts.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * hq db migrate — apply vault text migrations to local SQLite (US-005).
3
+ */
4
+
5
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="58d60a42-0362-59a3-a31e-c05f1a8dfc1e")}catch(e){}}();
6
+ import chalk from "chalk";
7
+ import path from "node:path";
8
+ import { migrateLocalDb } from "../lib/db/migrate.js";
9
+ const DEFAULT_HQ_ROOT = process.env.HQ_ROOT || path.resolve(process.cwd());
10
+ export function registerDbMigrateCommand(db) {
11
+ db.command("migrate")
12
+ .description("Apply pending vault text migrations (companies/{co}/db/migrations/*.sql) to the local DB")
13
+ .requiredOption("--company <slug>", "Company slug (tenant scope; required)")
14
+ .option("--hq-root <path>", "HQ tree root containing companies/ (default: cwd or HQ_ROOT)", DEFAULT_HQ_ROOT)
15
+ .option("--home <path>", "Override home for local DB root (tests)")
16
+ .action((opts) => {
17
+ try {
18
+ const company = String(opts.company ?? "").trim();
19
+ if (!company) {
20
+ console.error(chalk.red("Error: --company is required"));
21
+ process.exitCode = 1;
22
+ return;
23
+ }
24
+ const result = migrateLocalDb({
25
+ company,
26
+ hqRoot: opts.hqRoot || DEFAULT_HQ_ROOT,
27
+ ...(opts.home ? { home: opts.home } : {}),
28
+ });
29
+ console.log(`company: ${result.company}`);
30
+ console.log(`migrationsDir: ${result.migrationsDir}`);
31
+ console.log(`applied: ${result.applied.length ? result.applied.join(", ") : "(none)"}`);
32
+ console.log(`skipped: ${result.skipped.length ? result.skipped.join(", ") : "(none)"}`);
33
+ console.log(`schemaVersion: ${result.head ?? "(none)"}`);
34
+ }
35
+ catch (error) {
36
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
37
+ process.exitCode = 1;
38
+ }
39
+ });
40
+ }
41
+ //# sourceMappingURL=db-migrate.js.map
42
+ //# debugId=58d60a42-0362-59a3-a31e-c05f1a8dfc1e
@@ -0,0 +1,15 @@
1
+ /**
2
+ * hq db provision — request remote vault DB binding (US-009).
3
+ */
4
+ import { Command } from "commander";
5
+ export interface DbProvisionCommandDeps {
6
+ resolveCompany: (slug: string) => Promise<{
7
+ companyUid: string;
8
+ companySlug: string;
9
+ }>;
10
+ getAccessToken: () => Promise<string>;
11
+ apiBaseUrl: string;
12
+ fetchImpl?: typeof fetch;
13
+ }
14
+ export declare function registerDbProvisionCommand(db: Command, depsFactory?: () => DbProvisionCommandDeps): void;
15
+ //# sourceMappingURL=db-provision.d.ts.map
@@ -0,0 +1,78 @@
1
+ /**
2
+ * hq db provision — request remote vault DB binding (US-009).
3
+ */
4
+
5
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="cecdf1ea-3f73-54c4-adc0-f11caebf1e55")}catch(e){}}();
6
+ import chalk from "chalk";
7
+ import { ControlPlaneDbClient } from "../lib/db/control-plane.js";
8
+ const defaultDeps = () => ({
9
+ async resolveCompany(slug) {
10
+ // Production path: resolve via vault API membership. Tests inject mocks.
11
+ // Keep slug as placeholder uid only when HQ_DB_MOCK_CONTROL_PLANE=1.
12
+ if (process.env.HQ_DB_MOCK_CONTROL_PLANE === "1") {
13
+ return { companyUid: `cmp_${slug}`, companySlug: slug };
14
+ }
15
+ throw new Error("company resolution not wired in this build path — inject deps or set HQ_DB_MOCK_CONTROL_PLANE=1 for local mock");
16
+ },
17
+ async getAccessToken() {
18
+ if (process.env.HQ_DB_MOCK_CONTROL_PLANE === "1") {
19
+ return "mock-token";
20
+ }
21
+ throw new Error("auth token resolution not wired — inject deps for production");
22
+ },
23
+ apiBaseUrl: process.env.HQ_API_BASE_URL ||
24
+ process.env.HQ_CLOUD_API_URL ||
25
+ "https://hqapi.getindigo.ai",
26
+ });
27
+ export function registerDbProvisionCommand(db, depsFactory = defaultDeps) {
28
+ db.command("provision")
29
+ .description("Provision (or re-bind) the company remote vault DB via HQ control plane")
30
+ .requiredOption("--company <slug>", "Company slug")
31
+ .option("--region <region>", "AWS region", "us-east-1")
32
+ .action(async (opts) => {
33
+ try {
34
+ const deps = depsFactory();
35
+ const company = String(opts.company ?? "").trim();
36
+ if (!company) {
37
+ console.error(chalk.red("Error: --company is required"));
38
+ process.exitCode = 1;
39
+ return;
40
+ }
41
+ const resolved = await deps.resolveCompany(company);
42
+ const client = new ControlPlaneDbClient({
43
+ baseUrl: deps.apiBaseUrl,
44
+ getAccessToken: deps.getAccessToken,
45
+ fetchImpl: deps.fetchImpl,
46
+ });
47
+ const result = await client.provision({
48
+ companyUid: resolved.companyUid,
49
+ companySlug: resolved.companySlug,
50
+ region: opts.region,
51
+ });
52
+ console.log(`company: ${result.companySlug}`);
53
+ console.log(`remote: ${result.status}`);
54
+ console.log(`engine: ${result.engineId}`);
55
+ console.log(`region: ${result.region}`);
56
+ console.log(`resourceArn: ${result.resourceArn}`);
57
+ console.log(`secretRef: ${result.secretRef}`);
58
+ console.log(`idempotent: ${result.idempotent ? "yes" : "no"}`);
59
+ }
60
+ catch (error) {
61
+ const msg = error instanceof Error ? error.message : "Unknown error";
62
+ const status = error.status;
63
+ if (status === 402 || /PLAN_REQUIRED|Team plan|\$500/i.test(msg)) {
64
+ console.error(chalk.red("Error:"), "Remote vault DB requires the HQ Team plan ($500/mo).");
65
+ console.error(chalk.dim("Local databases still work: hq db status|sql|migrate — no Team plan required."));
66
+ }
67
+ else {
68
+ console.error(chalk.red("Error:"), msg);
69
+ }
70
+ if (/postgres:\/\//i.test(msg)) {
71
+ console.error(chalk.red("Error: refused to print secret material"));
72
+ }
73
+ process.exitCode = 1;
74
+ }
75
+ });
76
+ }
77
+ //# sourceMappingURL=db-provision.js.map
78
+ //# debugId=cecdf1ea-3f73-54c4-adc0-f11caebf1e55
@@ -0,0 +1,9 @@
1
+ /**
2
+ * hq db sql — run SQL against the company local vault DB (US-004).
3
+ *
4
+ * Default is read-only. Prefer `hq db migrate` for schema changes.
5
+ * Never prints remote connection strings.
6
+ */
7
+ import { Command } from "commander";
8
+ export declare function registerDbSqlCommand(db: Command): void;
9
+ //# sourceMappingURL=db-sql.d.ts.map