@indigoai-us/hq-cli 5.345.162 → 5.345.163

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.
@@ -0,0 +1,67 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * Staff triage commands on the feedback queue: `hq feedback list`,
4
+ * `hq feedback triage` and `hq feedback close`. `hq feedback assign` lives in
5
+ * feedback.ts next to the shared helpers.
6
+ *
7
+ * The server owns triagedAt, triagedBy and priority. These commands never
8
+ * send them.
9
+ */
10
+ export declare const TRIAGE_KINDS: readonly ["bug", "feature", "question"];
11
+ export type TriageKind = (typeof TRIAGE_KINDS)[number];
12
+ export declare const MAX_TRIAGE_SUMMARY = 2000;
13
+ export declare const DEFAULT_LIST_LIMIT = 50;
14
+ export interface FeedbackListRow {
15
+ id: string;
16
+ title?: string;
17
+ plan?: string;
18
+ submittedAt?: string;
19
+ createdAt?: string;
20
+ [key: string]: unknown;
21
+ }
22
+ export type FeedbackListSelector = {
23
+ kind: "untriaged";
24
+ } | {
25
+ kind: "assignee";
26
+ assignee: string;
27
+ };
28
+ /** Email claim of the caller's staff token, used by `list --mine`. */
29
+ export declare function emailFromToken(token: string): string | null;
30
+ /** Compact age such as `5m`, `3h` or `2d`. Unknown or unparsable times print `-`. */
31
+ export declare function formatFeedbackAge(iso: string | undefined, now?: number): string;
32
+ /**
33
+ * hq-pro's `GET /v1/feedback` returns the next page as `nextCursor` on every
34
+ * path (the untriaged queue also mirrors it as `cursor`) and reads it back from
35
+ * `?cursor=`. `nextToken` is accepted for older servers. The value always goes
36
+ * back as `?cursor=`.
37
+ */
38
+ export declare function cursorFrom(data: unknown): string | null;
39
+ /** Page through `GET /v1/feedback` until `limit` rows (or every row with `limit: null`). */
40
+ export declare function listFeedback(opts: {
41
+ token: string;
42
+ selector: FeedbackListSelector;
43
+ status?: string;
44
+ limit: number | null;
45
+ }): Promise<FeedbackListRow[]>;
46
+ export declare function formatFeedbackTable(rows: FeedbackListRow[], now?: number): string;
47
+ export declare function parseListLimit(raw: string): number;
48
+ export declare function buildTriagePatch(opts: {
49
+ id: string;
50
+ kind: string;
51
+ area: string;
52
+ summary: string;
53
+ duplicateOf?: string;
54
+ }): Record<string, string>;
55
+ export declare function buildClosePatch(opts: {
56
+ reason: string;
57
+ wontFix?: boolean;
58
+ }): Record<string, string>;
59
+ /** PATCH one feedback row; returns the server's JSON, or the sent fields when the body is empty. */
60
+ export declare function patchFeedback(opts: {
61
+ id: string;
62
+ token: string;
63
+ body: Record<string, string>;
64
+ action: string;
65
+ }): Promise<unknown>;
66
+ export declare function registerFeedbackTriageCommands(feedbackCmd: Command): void;
67
+ //# sourceMappingURL=feedback-triage.d.ts.map
@@ -0,0 +1,294 @@
1
+ import chalk from "chalk";
2
+ import { assertVaultApiRequestSupported, vaultApiFetch } from "../utils/vault-api.js";
3
+ import { decodeJwtPayload } from "../utils/person-token-cache.js";
4
+ import { assertFeedbackId, normalizeFeedbackAssignee, readFeedbackError, resolveStaffToken, } from "./feedback.js";
5
+ /**
6
+ * Staff triage commands on the feedback queue: `hq feedback list`,
7
+ * `hq feedback triage` and `hq feedback close`. `hq feedback assign` lives in
8
+ * feedback.ts next to the shared helpers.
9
+ *
10
+ * The server owns triagedAt, triagedBy and priority. These commands never
11
+ * send them.
12
+ */
13
+ export const TRIAGE_KINDS = ["bug", "feature", "question"];
14
+ export const MAX_TRIAGE_SUMMARY = 2000;
15
+ export const DEFAULT_LIST_LIMIT = 50;
16
+ /** Safety stop for --all so a server that never ends its cursor can't loop forever. */
17
+ const MAX_LIST_PAGES = 100;
18
+ function fail(err) {
19
+ console.error(chalk.red("Error:"), err instanceof Error ? err.message : String(err));
20
+ process.exit(1);
21
+ }
22
+ /** Email claim of the caller's staff token, used by `list --mine`. */
23
+ export function emailFromToken(token) {
24
+ const claims = decodeJwtPayload(token);
25
+ const email = claims?.email;
26
+ return typeof email === "string" && email.includes("@") ? email.toLowerCase() : null;
27
+ }
28
+ /** Compact age such as `5m`, `3h` or `2d`. Unknown or unparsable times print `-`. */
29
+ export function formatFeedbackAge(iso, now = Date.now()) {
30
+ if (!iso)
31
+ return "-";
32
+ const at = Date.parse(iso);
33
+ if (Number.isNaN(at))
34
+ return "-";
35
+ const minutes = Math.max(0, Math.floor((now - at) / 60_000));
36
+ if (minutes < 60)
37
+ return `${minutes}m`;
38
+ const hours = Math.floor(minutes / 60);
39
+ if (hours < 48)
40
+ return `${hours}h`;
41
+ return `${Math.floor(hours / 24)}d`;
42
+ }
43
+ function rowsFrom(data) {
44
+ if (!data || typeof data !== "object" || Array.isArray(data))
45
+ return [];
46
+ const items = data.items;
47
+ if (!Array.isArray(items))
48
+ return [];
49
+ return items.filter((row) => !!row && typeof row === "object" && typeof row.id === "string");
50
+ }
51
+ /**
52
+ * hq-pro's `GET /v1/feedback` returns the next page as `nextCursor` on every
53
+ * path (the untriaged queue also mirrors it as `cursor`) and reads it back from
54
+ * `?cursor=`. `nextToken` is accepted for older servers. The value always goes
55
+ * back as `?cursor=`.
56
+ */
57
+ export function cursorFrom(data) {
58
+ if (!data || typeof data !== "object" || Array.isArray(data))
59
+ return null;
60
+ for (const name of ["nextCursor", "cursor", "nextToken"]) {
61
+ const value = data[name];
62
+ if (typeof value === "string" && value.length > 0)
63
+ return value;
64
+ }
65
+ return null;
66
+ }
67
+ /** Server page cap (FEEDBACK_LIST_PAGE_MAX). The plain list path rejects a cursor without a limit. */
68
+ const LIST_PAGE_SIZE = 200;
69
+ /** Page through `GET /v1/feedback` until `limit` rows (or every row with `limit: null`). */
70
+ export async function listFeedback(opts) {
71
+ const base = opts.selector.kind === "untriaged"
72
+ ? { triage: "untriaged" }
73
+ : { assignee: opts.selector.assignee };
74
+ if (opts.status)
75
+ base.status = opts.status;
76
+ const rows = [];
77
+ let cursor = null;
78
+ for (let page = 0; page < MAX_LIST_PAGES; page++) {
79
+ const pageSize = opts.limit === null ? LIST_PAGE_SIZE : Math.min(LIST_PAGE_SIZE, opts.limit - rows.length);
80
+ const query = { ...base, limit: String(pageSize) };
81
+ if (cursor)
82
+ query.cursor = cursor;
83
+ const res = await vaultApiFetch({ token: opts.token, path: "/v1/feedback", query });
84
+ if (!res.ok) {
85
+ throw new Error(`Failed to list feedback: ${await readFeedbackError(res)}`);
86
+ }
87
+ const data = (await res.json());
88
+ rows.push(...rowsFrom(data));
89
+ if (opts.limit !== null && rows.length >= opts.limit)
90
+ return rows.slice(0, opts.limit);
91
+ cursor = cursorFrom(data);
92
+ if (!cursor)
93
+ return rows;
94
+ }
95
+ return rows;
96
+ }
97
+ export function formatFeedbackTable(rows, now = Date.now()) {
98
+ const header = ["ID", "AGE", "PLAN", "TITLE"];
99
+ const body = rows.map((row) => [
100
+ row.id,
101
+ formatFeedbackAge(row.submittedAt ?? row.createdAt, now),
102
+ typeof row.plan === "string" && row.plan.length > 0 ? row.plan : "-",
103
+ typeof row.title === "string" ? row.title : "",
104
+ ]);
105
+ const widths = [0, 1, 2].map((col) => Math.max(header[col].length, ...body.map((cells) => cells[col].length)));
106
+ return [header, ...body]
107
+ .map((cells) => cells.map((cell, col) => (col < 3 ? cell.padEnd(widths[col]) : cell)).join(" ").trimEnd())
108
+ .join("\n");
109
+ }
110
+ export function parseListLimit(raw) {
111
+ const n = Number(raw);
112
+ if (!Number.isInteger(n) || n < 1) {
113
+ throw new Error(`Invalid --limit '${raw}': expected a positive whole number.`);
114
+ }
115
+ return n;
116
+ }
117
+ export function buildTriagePatch(opts) {
118
+ if (!TRIAGE_KINDS.includes(opts.kind)) {
119
+ throw new Error(`Invalid --kind '${opts.kind}': expected one of ${TRIAGE_KINDS.join(", ")}.`);
120
+ }
121
+ const area = opts.area.trim();
122
+ if (!area)
123
+ throw new Error("--area must not be empty.");
124
+ const summary = opts.summary.trim();
125
+ if (!summary)
126
+ throw new Error("--summary must not be empty.");
127
+ if (summary.length > MAX_TRIAGE_SUMMARY) {
128
+ throw new Error(`--summary is ${summary.length} characters; the limit is ${MAX_TRIAGE_SUMMARY}.`);
129
+ }
130
+ const body = {
131
+ triageStatus: opts.duplicateOf === undefined ? "triaged" : "duplicate",
132
+ triageKind: opts.kind,
133
+ area,
134
+ summary,
135
+ };
136
+ if (opts.duplicateOf !== undefined) {
137
+ assertFeedbackId(opts.duplicateOf);
138
+ if (opts.duplicateOf === opts.id) {
139
+ throw new Error("--duplicate-of must name a different feedback item.");
140
+ }
141
+ body.duplicateOf = opts.duplicateOf;
142
+ }
143
+ return body;
144
+ }
145
+ export function buildClosePatch(opts) {
146
+ const reason = opts.reason.trim();
147
+ if (!reason)
148
+ throw new Error("--reason must not be empty.");
149
+ return { status: opts.wontFix ? "wont_fix" : "resolved", resolution: reason };
150
+ }
151
+ /** PATCH one feedback row; returns the server's JSON, or the sent fields when the body is empty. */
152
+ export async function patchFeedback(opts) {
153
+ const res = await vaultApiFetch({
154
+ token: opts.token,
155
+ path: `/v1/feedback/${opts.id}`,
156
+ method: "PATCH",
157
+ body: opts.body,
158
+ });
159
+ if (!res.ok) {
160
+ throw new Error(`Failed to ${opts.action} ${opts.id}: ${await readFeedbackError(res)}`);
161
+ }
162
+ const data = (await res.json().catch(() => null));
163
+ return data ?? { id: opts.id, ...opts.body };
164
+ }
165
+ function registerListSubcommand(feedbackCmd) {
166
+ feedbackCmd
167
+ .command("list")
168
+ .description("List feedback: untriaged (default), yours, or one person's")
169
+ .option("--untriaged", "Items nobody has triaged yet (the default)")
170
+ .option("--mine", "Items assigned to you")
171
+ .option("--assignee <person>", "Items assigned to this email address or prs_ uid")
172
+ .option("--status <status>", "Only items with this status")
173
+ .option("--limit <n>", `Stop after this many items (default ${DEFAULT_LIST_LIMIT})`)
174
+ .option("--all", "Fetch every page")
175
+ .option("--json", "Print { items, count } as JSON")
176
+ .action(async (opts) => {
177
+ try {
178
+ const picked = [opts.untriaged, opts.mine, opts.assignee !== undefined].filter(Boolean);
179
+ if (picked.length > 1) {
180
+ throw new Error("Use only one of --untriaged, --mine and --assignee.");
181
+ }
182
+ if (opts.all && opts.limit !== undefined) {
183
+ throw new Error("Use --limit or --all, not both.");
184
+ }
185
+ if (opts.status !== undefined && !opts.status.trim()) {
186
+ throw new Error("--status must not be empty.");
187
+ }
188
+ const limit = opts.all
189
+ ? null
190
+ : opts.limit === undefined
191
+ ? DEFAULT_LIST_LIMIT
192
+ : parseListLimit(opts.limit);
193
+ const token = await resolveStaffToken();
194
+ let selector = { kind: "untriaged" };
195
+ if (opts.mine) {
196
+ const email = emailFromToken(token);
197
+ if (!email) {
198
+ throw new Error("--mine needs a person login with an email (hq login). Use --assignee <person> instead.");
199
+ }
200
+ selector = { kind: "assignee", assignee: email };
201
+ }
202
+ else if (opts.assignee !== undefined) {
203
+ selector = {
204
+ kind: "assignee",
205
+ assignee: normalizeFeedbackAssignee(opts.assignee, "--assignee"),
206
+ };
207
+ }
208
+ assertVaultApiRequestSupported({ token, path: "/v1/feedback" });
209
+ const items = await listFeedback({
210
+ token,
211
+ selector,
212
+ status: opts.status?.trim(),
213
+ limit,
214
+ });
215
+ if (opts.json) {
216
+ console.log(JSON.stringify({ items, count: items.length }));
217
+ }
218
+ else if (items.length === 0) {
219
+ console.log("No feedback items match.");
220
+ }
221
+ else {
222
+ console.log(formatFeedbackTable(items));
223
+ }
224
+ }
225
+ catch (err) {
226
+ fail(err);
227
+ }
228
+ });
229
+ }
230
+ function registerTriageSubcommand(feedbackCmd) {
231
+ feedbackCmd
232
+ .command("triage")
233
+ .description("Label a feedback item with its kind, area and summary, or mark it a duplicate")
234
+ .argument("<id>", "Feedback id (feedback_<uuid>)")
235
+ .requiredOption("--kind <kind>", `One of ${TRIAGE_KINDS.join(", ")}`)
236
+ .requiredOption("--area <area>", "Product area, for example sync or desktop")
237
+ .requiredOption("--summary <text>", `One-line triage summary (at most ${MAX_TRIAGE_SUMMARY} characters)`)
238
+ .option("--duplicate-of <id>", "Mark this item a duplicate of another feedback id")
239
+ .option("--json", "Print the updated item as JSON")
240
+ .action(async (id, opts) => {
241
+ try {
242
+ assertFeedbackId(id);
243
+ const body = buildTriagePatch({ id, ...opts });
244
+ const token = await resolveStaffToken();
245
+ assertVaultApiRequestSupported({ token, path: `/v1/feedback/${id}` });
246
+ const result = await patchFeedback({ id, token, body, action: "triage" });
247
+ if (opts.json) {
248
+ console.log(JSON.stringify(result));
249
+ }
250
+ else if (body.duplicateOf) {
251
+ console.log(`Marked duplicate: ${id} -> ${body.duplicateOf}`);
252
+ }
253
+ else {
254
+ console.log(`Triaged: ${id} (${body.triageKind}, ${body.area})`);
255
+ }
256
+ }
257
+ catch (err) {
258
+ fail(err);
259
+ }
260
+ });
261
+ }
262
+ function registerCloseSubcommand(feedbackCmd) {
263
+ feedbackCmd
264
+ .command("close")
265
+ .description("Close a feedback item as resolved (or won't fix) with a reason")
266
+ .argument("<id>", "Feedback id (feedback_<uuid>)")
267
+ .requiredOption("--reason <text>", "Why it is closed: the fix, PR or version, or the decision")
268
+ .option("--wont-fix", "Close as won't fix instead of resolved")
269
+ .option("--json", "Print the updated item as JSON")
270
+ .action(async (id, opts) => {
271
+ try {
272
+ assertFeedbackId(id);
273
+ const body = buildClosePatch(opts);
274
+ const token = await resolveStaffToken();
275
+ assertVaultApiRequestSupported({ token, path: `/v1/feedback/${id}` });
276
+ const result = await patchFeedback({ id, token, body, action: "close" });
277
+ if (opts.json) {
278
+ console.log(JSON.stringify(result));
279
+ }
280
+ else {
281
+ console.log(`Closed: ${id} (${body.status})`);
282
+ }
283
+ }
284
+ catch (err) {
285
+ fail(err);
286
+ }
287
+ });
288
+ }
289
+ export function registerFeedbackTriageCommands(feedbackCmd) {
290
+ registerListSubcommand(feedbackCmd);
291
+ registerTriageSubcommand(feedbackCmd);
292
+ registerCloseSubcommand(feedbackCmd);
293
+ }
294
+ //# sourceMappingURL=feedback-triage.js.map
@@ -76,6 +76,13 @@ export declare function submitFeedback(opts: FeedbackSubmitOptions): Promise<Fee
76
76
  export declare const PUBLIC_TICKET_STATES: readonly ["triaged", "in-progress", "shipped", "verified", "resolved"];
77
77
  export type PublicTicketState = (typeof PUBLIC_TICKET_STATES)[number];
78
78
  export declare function assertFeedbackId(id: string): void;
79
+ /**
80
+ * The staff feedback routes gate on the id token's email claim, so send the
81
+ * cached id token when a person session has one. Machine identities already
82
+ * get their id token back from ensureCognitoToken.
83
+ */
84
+ export declare function resolveStaffToken(): Promise<string>;
85
+ export declare function readFeedbackError(res: Response): Promise<string>;
79
86
  /** Resolve (and lazily mint) the public tracking link for a ticket. */
80
87
  export declare function fetchFeedbackLink(opts: {
81
88
  id: string;
@@ -92,7 +99,7 @@ export declare function postFeedbackUpdate(opts: {
92
99
  slack: string | null;
93
100
  }>;
94
101
  /** Mirror of hq-pro normalizeAssignee: a prs_ uid as-is, an email lowercased. */
95
- export declare function normalizeFeedbackAssignee(value: string): string;
102
+ export declare function normalizeFeedbackAssignee(value: string, label?: string): string;
96
103
  /**
97
104
  * Reassign a ticket. A person's own login may move a ticket that another
98
105
  * person claimed; agent and operator service tokens get 409
@@ -103,5 +110,10 @@ export declare function assignFeedback(opts: {
103
110
  token: string;
104
111
  assignee: string;
105
112
  }): Promise<void>;
113
+ /**
114
+ * Pick the new assignee from the positional `[person]` or the `--to` flag.
115
+ * Either form works; naming two different people is an error.
116
+ */
117
+ export declare function resolveAssignTarget(person: string | undefined, to: string | undefined): string;
106
118
  export declare function registerFeedbackCommand(program: Command): void;
107
119
  //# sourceMappingURL=feedback.d.ts.map
@@ -9,6 +9,7 @@ import { uploadLogBundle } from "../utils/feedback-log-bundle.js";
9
9
  import { resolveProcessFlagGate } from "../lib/flag-registry.js";
10
10
  import { cachedLatestVersion } from "../utils/version-check.js";
11
11
  import { registerFeedbackShowCommand } from "./feedback-show.js";
12
+ import { registerFeedbackTriageCommands } from "./feedback-triage.js";
12
13
  export const FEEDBACK_LATEST_VERSION_FLAG = "feedback.latest-version";
13
14
  export const FEEDBACK_LATEST_VERSION_FLAG_FALLBACK = false;
14
15
  export const FEEDBACK_REPORTER_KIND_FLAG = "feedback.reporter-kind";
@@ -229,14 +230,14 @@ export function assertFeedbackId(id) {
229
230
  * cached id token when a person session has one. Machine identities already
230
231
  * get their id token back from ensureCognitoToken.
231
232
  */
232
- async function resolveStaffToken() {
233
+ export async function resolveStaffToken() {
233
234
  const token = await ensureCognitoToken({ interactive: false });
234
235
  const cached = loadCachedTokens();
235
236
  return typeof cached?.idToken === "string" && cached.idToken.length > 0
236
237
  ? cached.idToken
237
238
  : token;
238
239
  }
239
- async function readFeedbackError(res) {
240
+ export async function readFeedbackError(res) {
240
241
  const data = await res.json().catch(() => ({}));
241
242
  return data &&
242
243
  typeof data === "object" &&
@@ -287,10 +288,10 @@ export async function postFeedbackUpdate(opts) {
287
288
  }
288
289
  const ASSIGNEE_RE = /^(?:prs_[A-Za-z0-9]+|[^\s@]+@[^\s@]+\.[^\s@]+)$/;
289
290
  /** Mirror of hq-pro normalizeAssignee: a prs_ uid as-is, an email lowercased. */
290
- export function normalizeFeedbackAssignee(value) {
291
+ export function normalizeFeedbackAssignee(value, label = "--to") {
291
292
  const trimmed = value.trim();
292
293
  if (!ASSIGNEE_RE.test(trimmed)) {
293
- throw new Error(`Invalid --to '${value}': expected an email address or a prs_ uid.`);
294
+ throw new Error(`Invalid ${label} '${value}': expected an email address or a prs_ uid.`);
294
295
  }
295
296
  return trimmed.startsWith("prs_") ? trimmed : trimmed.toLowerCase();
296
297
  }
@@ -315,20 +316,42 @@ export async function assignFeedback(opts) {
315
316
  }
316
317
  throw new Error(`Failed to assign ${opts.id}: ${message}`);
317
318
  }
319
+ /**
320
+ * Pick the new assignee from the positional `[person]` or the `--to` flag.
321
+ * Either form works; naming two different people is an error.
322
+ */
323
+ export function resolveAssignTarget(person, to) {
324
+ if (person === undefined && to === undefined) {
325
+ throw new Error("Name the new assignee: hq feedback assign <id> <person> (or --to <person>).");
326
+ }
327
+ const fromPerson = person === undefined ? undefined : normalizeFeedbackAssignee(person, "person");
328
+ const fromTo = to === undefined ? undefined : normalizeFeedbackAssignee(to);
329
+ if (fromPerson !== undefined && fromTo !== undefined && fromPerson !== fromTo) {
330
+ throw new Error(`Conflicting assignees '${person}' and --to '${to}': give only one.`);
331
+ }
332
+ return (fromPerson ?? fromTo);
333
+ }
318
334
  function registerAssignSubcommand(feedbackCmd) {
319
335
  feedbackCmd
320
336
  .command("assign")
321
337
  .description("Reassign a ticket to a person, including one another person has claimed")
322
338
  .argument("<id>", "Feedback id (feedback_<uuid>)")
323
- .requiredOption("--to <assignee>", "New assignee: an email address or a prs_ uid")
324
- .action(async (id, opts) => {
339
+ .argument("[person]", "New assignee: an email address or a prs_ uid")
340
+ .option("--to <assignee>", "New assignee: an email address or a prs_ uid")
341
+ .option("--json", "Print the result as JSON")
342
+ .action(async (id, person, opts) => {
325
343
  try {
326
344
  assertFeedbackId(id);
327
- const assignee = normalizeFeedbackAssignee(opts.to);
345
+ const assignee = resolveAssignTarget(person, opts.to);
328
346
  const token = await resolveStaffToken();
329
347
  assertVaultApiRequestSupported({ token, path: `/v1/feedback/${id}` });
330
348
  await assignFeedback({ id, token, assignee });
331
- console.log(`Assigned: ${id} -> ${assignee}`);
349
+ if (opts.json) {
350
+ console.log(JSON.stringify({ id, assignee }));
351
+ }
352
+ else {
353
+ console.log(`Assigned: ${id} -> ${assignee}`);
354
+ }
332
355
  }
333
356
  catch (err) {
334
357
  console.error(chalk.red("Error:"), err instanceof Error ? err.message : String(err));
@@ -499,5 +522,6 @@ export function registerFeedbackCommand(program) {
499
522
  registerUpdateSubcommand(feedbackCmd);
500
523
  registerFeedbackShowCommand(feedbackCmd);
501
524
  registerAssignSubcommand(feedbackCmd);
525
+ registerFeedbackTriageCommands(feedbackCmd);
502
526
  }
503
527
  //# sourceMappingURL=feedback.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.345.162",
3
+ "version": "5.345.163",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -114,11 +114,11 @@
114
114
  "*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}": "eslint --cache --no-error-on-unmatched-pattern"
115
115
  },
116
116
  "optionalDependencies": {
117
- "@indigoai-us/hq-hook-win32-x64": "5.345.162",
118
- "@indigoai-us/hq-hook-win32-arm64": "5.345.162",
119
- "@indigoai-us/hq-hook-darwin-x64": "5.345.162",
120
- "@indigoai-us/hq-hook-darwin-arm64": "5.345.162",
121
- "@indigoai-us/hq-hook-linux-x64": "5.345.162",
122
- "@indigoai-us/hq-hook-linux-arm64": "5.345.162"
117
+ "@indigoai-us/hq-hook-win32-x64": "5.345.163",
118
+ "@indigoai-us/hq-hook-win32-arm64": "5.345.163",
119
+ "@indigoai-us/hq-hook-darwin-x64": "5.345.163",
120
+ "@indigoai-us/hq-hook-darwin-arm64": "5.345.163",
121
+ "@indigoai-us/hq-hook-linux-x64": "5.345.163",
122
+ "@indigoai-us/hq-hook-linux-arm64": "5.345.163"
123
123
  }
124
124
  }