@indigoai-us/hq-cli 5.342.16 → 5.342.17

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,10 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.342.17] — 2026-10-04
6
+ - Show agent display names in the agents list and accept them when selecting an agent.
7
+ - Resume due blocked keep-alive for story-less standing lead lanes, record no-open-story skips in lane history, and report the latest blocked skip in keep-alive audit.
8
+
5
9
  ## [5.342.16] — 2026-10-04
6
10
  - Keep resident command leases until monitor, agent, OAuth, bot, daemon and lane-watch runtime modules and their transitive Cognito, first-sync, hq-cloud and local-file dependencies are preloaded.
7
11
  - CI now runs the core utility parity assertions on Ubuntu, macOS, and Windows.
@@ -127,6 +127,7 @@ export interface CompanyAgentView {
127
127
  codexModel?: string;
128
128
  codexReasoningEffort?: string;
129
129
  codexServiceTier?: string;
130
+ displayName?: string;
130
131
  profile?: {
131
132
  displayName?: string;
132
133
  title?: string;
@@ -368,12 +369,6 @@ export interface DmThreadMessage {
368
369
  /** "out" = sent by the caller; "in" = received (the agent's reply). */
369
370
  direction: "in" | "out";
370
371
  }
371
- /**
372
- * Resolve an agent reference to its `agt_` uid. An `agt_…` value is used
373
- * directly; anything else is treated as a slug or display name and resolved
374
- * against the company's roster (requires `--company` or a single active
375
- * membership).
376
- */
377
372
  export declare function resolveAgentUid(token: string, ref: string, companySlug: string | undefined): Promise<string>;
378
373
  /**
379
374
  * Fail-closed local guard for the off-box `hq agents jobs` operator commands.
@@ -996,15 +996,26 @@ function catalogUnavailableMessage() {
996
996
  * against the company's roster (requires `--company` or a single active
997
997
  * membership).
998
998
  */
999
+ function effectiveAgentDisplayName(agent) {
1000
+ return agent.profile?.displayName || agent.displayName || agent.name || "";
1001
+ }
999
1002
  export async function resolveAgentUid(token, ref, companySlug) {
1000
1003
  if (AGENT_UID_PATTERN.test(ref.trim()))
1001
1004
  return ref.trim();
1002
1005
  const companyUid = await getCompanyUid(token, companySlug);
1003
1006
  const roster = await listAgents(token, companyUid);
1004
- const needle = ref.trim().toLowerCase();
1005
- const match = roster.find((a) => a.slug?.toLowerCase() === needle ||
1006
- a.name?.toLowerCase() === needle ||
1007
- a.uid === ref.trim());
1007
+ const trimmedRef = ref.trim();
1008
+ const needle = trimmedRef.toLowerCase();
1009
+ const exactMatch = roster.find((agent) => agent.slug?.toLowerCase() === needle) ??
1010
+ roster.find((agent) => agent.name?.toLowerCase() === needle) ??
1011
+ roster.find((agent) => agent.uid === trimmedRef);
1012
+ if (exactMatch)
1013
+ return exactMatch.uid;
1014
+ const displayNameMatches = roster.filter((agent) => effectiveAgentDisplayName(agent).toLowerCase() === needle);
1015
+ if (displayNameMatches.length > 1) {
1016
+ throw new AgentsHttpError(409, `More than one agent matches "${ref}" in this company. Use an agent slug or agt_ UID.`);
1017
+ }
1018
+ const match = displayNameMatches[0];
1008
1019
  if (!match) {
1009
1020
  throw new AgentsHttpError(404, `No agent named "${ref}" in this company. Run \`hq agents list\` to see slugs/uids, ` +
1010
1021
  `or pass the agt_ uid directly.`);
@@ -1697,7 +1708,7 @@ export function registerAgentsCommand(program) {
1697
1708
  console.log(chalk.gray("No agents found for this company."));
1698
1709
  return;
1699
1710
  }
1700
- const nameW = Math.max(4, ...roster.map((a) => (a.name ?? "").length));
1711
+ const nameW = Math.max(4, ...roster.map((agent) => effectiveAgentDisplayName(agent).length));
1701
1712
  const slugW = Math.max(4, ...roster.map((a) => (a.slug ?? "").length));
1702
1713
  const statusW = Math.max(6, ...roster.map((a) => rosterStatusLabel(a).length));
1703
1714
  const modelW = Math.max(5, ...roster.map((a) => (a.codexModel ?? "").length));
@@ -1710,7 +1721,7 @@ export function registerAgentsCommand(program) {
1710
1721
  ].join(" ")));
1711
1722
  for (const a of roster) {
1712
1723
  console.log([
1713
- (a.name ?? "").padEnd(nameW),
1724
+ effectiveAgentDisplayName(a).padEnd(nameW),
1714
1725
  (a.slug ?? "").padEnd(slugW),
1715
1726
  rosterStatusLabel(a).padEnd(statusW),
1716
1727
  (a.codexModel ?? "").padEnd(modelW),
@@ -355,8 +355,6 @@ function blockedKeepAliveOutcome(lane, stop, nextEnvelopeMs) {
355
355
  : Math.abs(terminal - stop.mtimeMs) <= 10 * 60_000;
356
356
  if (!sameStop)
357
357
  return [];
358
- if (entry.event === "keep_alive_blocked_skipped" && entry.reason !== "flag_off")
359
- return [];
360
358
  return [{
361
359
  status: entry.event === "keep_alive_blocked_resumed" ? "woken" : "skipped",
362
360
  ...(entry.reason === undefined ? {} : { reason: entry.reason }),
@@ -2328,8 +2328,9 @@ async function resumeBlockedKeepAlive(hqRoot, lane, questions, summary, deps, no
2328
2328
  recordKeepAliveSkip(hqRoot, lane, "missing_interruption_time", summary, deps, "blocked terminal time is invalid");
2329
2329
  return;
2330
2330
  }
2331
- if (activeLaneStories(lane).length === 0) {
2331
+ if (laneStories(lane).length > 0 && activeLaneStories(lane).length === 0) {
2332
2332
  summary.skipped.push({ kind: "lane", id: lane.lane_id, why: "keep_alive_no_open_stories" });
2333
+ recordBlockedKeepAliveSkipEvent(hqRoot, lane, "no_open_stories", summary, deps);
2333
2334
  return;
2334
2335
  }
2335
2336
  let pendingQuestion = questions.some((question) => question.lane_id === lane.lane_id && question.status === "pending");
@@ -2496,6 +2497,27 @@ function recordBlockedKeepAliveFlagOff(hqRoot, lane, summary, deps) {
2496
2497
  markDirty(summary, { kind: "lane", id: lane.lane_id, why: `blocked keep-alive skip record failed: ${err instanceof Error ? err.message : String(err)}` });
2497
2498
  }
2498
2499
  }
2500
+ function recordBlockedKeepAliveSkipEvent(hqRoot, lane, reason, summary, deps) {
2501
+ const terminalAt = lane.last_envelope?.at;
2502
+ if (deps.dryRun || lane.last_envelope?.decision !== "blocked" || terminalAt === undefined)
2503
+ return;
2504
+ if (lane.status_gate_history?.some((entry) => entry.event === "keep_alive_blocked_skipped" && entry.terminal_at === terminalAt && entry.reason === reason))
2505
+ return;
2506
+ try {
2507
+ casLaneIf(hqRoot, lane.lane_id, (current) => current.version === lane.version && current.state === "blocked" && current.last_envelope?.at === terminalAt, (current) => ({
2508
+ ...current,
2509
+ status_gate_history: appendCappedHistory(current.status_gate_history ?? [], {
2510
+ event: "keep_alive_blocked_skipped",
2511
+ at: deps.now().toISOString(),
2512
+ terminal_at: terminalAt,
2513
+ reason,
2514
+ }),
2515
+ }), false);
2516
+ }
2517
+ catch (err) {
2518
+ markDirty(summary, { kind: "lane", id: lane.lane_id, why: `blocked keep-alive skip record failed: ${err instanceof Error ? err.message : String(err)}` });
2519
+ }
2520
+ }
2499
2521
  function appendBlockedKeepAliveHistory(hqRoot, lane, terminalAt, at, reason, deps) {
2500
2522
  if (deps.dryRun || lane.status_gate_history?.some((entry) => entry.event === "keep_alive_blocked_grace" && entry.terminal_at === terminalAt && entry.resume_skipped_reason === reason))
2501
2523
  return;
@@ -449,7 +449,7 @@ export interface KeepAliveBlockedHistoryEntry {
449
449
  at: string;
450
450
  terminal_at: string;
451
451
  resume_skipped_reason?: "open_question" | "blocked_grace";
452
- reason?: "flag_off" | "backoff" | "next_check_at_due";
452
+ reason?: "flag_off" | "backoff" | "next_check_at_due" | "no_open_stories";
453
453
  resume_queued?: boolean;
454
454
  }
455
455
  export interface KeepAliveResumeHistoryEntry {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.342.16",
3
+ "version": "5.342.17",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {