@indigoai-us/hq-cli 5.140.0 → 5.141.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
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.141.0] — 2026-09-23
|
|
6
|
+
|
|
7
|
+
- `hq bot jobs` now checks the bot's configured agent ID against the machine credential before calling the jobs API. A mismatch reports both IDs and explains how to fix the bot configuration or re-mint its credentials.
|
|
8
|
+
|
|
5
9
|
## [5.140.0] — 2026-09-23
|
|
6
10
|
|
|
7
11
|
### Fixed
|
|
@@ -20,6 +20,7 @@ import * as fs from "node:fs";
|
|
|
20
20
|
import * as path from "node:path";
|
|
21
21
|
import { BotApi, BotApiError } from "../lib/bot/api.js";
|
|
22
22
|
import { effectiveBotKind } from "../lib/bot/config.js";
|
|
23
|
+
import { identityMismatchMessage, tokenAgentUid } from "../lib/heartbeat-identity.js";
|
|
23
24
|
// ─── Schedule translation ────────────────────────────────────────────────────
|
|
24
25
|
/** Mirrors hq-pro-agents `MIN_RECURRING_INTERVAL_SECONDS`. */
|
|
25
26
|
export const MIN_RECURRING_INTERVAL_SECONDS = 5 * 60;
|
|
@@ -363,10 +364,19 @@ export async function runBotJobs(nameArg, opts, deps) {
|
|
|
363
364
|
const { name, dir, config } = deps.requireBot(nameArg);
|
|
364
365
|
const kind = effectiveBotKind(config);
|
|
365
366
|
const out = deps.out ?? ((line) => console.log(line));
|
|
366
|
-
const api = deps.apiFor
|
|
367
|
-
? deps.apiFor(dir)
|
|
368
|
-
: new BotApi({ token: deps.botTokenSupplier(dir) });
|
|
369
367
|
const ctx = { botName: name, kind };
|
|
368
|
+
let client;
|
|
369
|
+
const jobsApi = async () => {
|
|
370
|
+
if (client)
|
|
371
|
+
return client;
|
|
372
|
+
const token = await deps.botTokenSupplier(dir)();
|
|
373
|
+
const tokenUid = tokenAgentUid(token);
|
|
374
|
+
if (tokenUid && tokenUid !== config.agentUid) {
|
|
375
|
+
refuse(identityMismatchMessage("bot jobs", config.agentUid, tokenUid));
|
|
376
|
+
}
|
|
377
|
+
client = deps.apiFor ? deps.apiFor(dir) : new BotApi({ token: async () => token });
|
|
378
|
+
return client;
|
|
379
|
+
};
|
|
370
380
|
if (opts.add !== undefined && opts.rm !== undefined) {
|
|
371
381
|
refuse("Add a job or remove one, not both in the same command.");
|
|
372
382
|
}
|
|
@@ -374,6 +384,7 @@ export async function runBotJobs(nameArg, opts, deps) {
|
|
|
374
384
|
const jobId = opts.rm.trim();
|
|
375
385
|
if (!jobId)
|
|
376
386
|
refuse("Say which job to remove: --rm <jobId>");
|
|
387
|
+
const api = await jobsApi();
|
|
377
388
|
try {
|
|
378
389
|
await api.cancelJob(config.agentUid, jobId);
|
|
379
390
|
}
|
|
@@ -395,6 +406,7 @@ export async function runBotJobs(nameArg, opts, deps) {
|
|
|
395
406
|
? parse(opts.every, { hqRoot: config.hqRoot, timezone })
|
|
396
407
|
: { cron: opts.cron, timezone };
|
|
397
408
|
const body = buildCreateJobBody({ prompt: opts.add, cron: schedule.cron, timezone: schedule.timezone });
|
|
409
|
+
const api = await jobsApi();
|
|
398
410
|
let created;
|
|
399
411
|
try {
|
|
400
412
|
created = await api.createJob(config.agentUid, body);
|
|
@@ -414,6 +426,7 @@ export async function runBotJobs(nameArg, opts, deps) {
|
|
|
414
426
|
return;
|
|
415
427
|
}
|
|
416
428
|
let jobs;
|
|
429
|
+
const api = await jobsApi();
|
|
417
430
|
try {
|
|
418
431
|
jobs = await api.listJobs(config.agentUid);
|
|
419
432
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import * as fs from "node:fs";
|
|
15
15
|
import * as os from "node:os";
|
|
16
16
|
import { CLI_VERSION } from "../../../cli-version.js";
|
|
17
|
-
import { captureHeartbeatIdentityMismatch, isHeartbeatIdentityMismatch, parseHeartbeatFailureBody, tokenAgentUid, } from "../../heartbeat-identity.js";
|
|
17
|
+
import { captureHeartbeatIdentityMismatch, identityMismatchMessage, isHeartbeatIdentityMismatch, parseHeartbeatFailureBody, tokenAgentUid, } from "../../heartbeat-identity.js";
|
|
18
18
|
import { vaultApiFetch } from "../../../utils/vault-api.js";
|
|
19
19
|
import { readComponentStatus } from "../creds.js";
|
|
20
20
|
import { KIT_COMPONENTS } from "../paths.js";
|
|
@@ -90,7 +90,7 @@ async function beatOnceResult(deps) {
|
|
|
90
90
|
...(tokenUid ? { tokenAgentUid: tokenUid } : {}),
|
|
91
91
|
});
|
|
92
92
|
const tokenLabel = tokenUid ?? "unknown";
|
|
93
|
-
deps.log("warn",
|
|
93
|
+
deps.log("warn", identityMismatchMessage("heartbeat", deps.agentUid, tokenLabel));
|
|
94
94
|
(deps.reportIdentityMismatch ?? captureHeartbeatIdentityMismatch)({
|
|
95
95
|
runner: "agent-kit",
|
|
96
96
|
configuredAgentUid: deps.agentUid,
|
package/dist/lib/bot/run.js
CHANGED
|
@@ -69,7 +69,7 @@ import { buildJobTurnPrompt, isCatchUpRun, isJobItem, jobReportHeader, jobRunOut
|
|
|
69
69
|
import { clearPendingJobCompletion, isCompletionDue, isCompletionExpired, isCompletionForOtherAgent, readPendingJobCompletions, recordPendingJobCompletion } from "./job-completions.js";
|
|
70
70
|
import { isRuntimeSignInFailure, SIGN_IN_RETRY_MS, signInNeededText } from "./runtime-sign-in.js";
|
|
71
71
|
import { HQ_BOT_AGENT_UID_ENV } from "../../commands/onboard-bot-membership.js";
|
|
72
|
-
import { captureHeartbeatIdentityMismatch, isHeartbeatIdentityMismatch, } from "../heartbeat-identity.js";
|
|
72
|
+
import { captureHeartbeatIdentityMismatch, identityMismatchMessage, isHeartbeatIdentityMismatch, } from "../heartbeat-identity.js";
|
|
73
73
|
import { clearBotSession, readBotSession, writeBotSession } from "./session.js";
|
|
74
74
|
import { defaultBotStatus, patchBotStatus, readBotStatus } from "./status.js";
|
|
75
75
|
export const INBOX_POLL_INTERVAL_MS = 2_000;
|
|
@@ -459,7 +459,7 @@ export async function runBot(deps) {
|
|
|
459
459
|
if (err instanceof BotApiError &&
|
|
460
460
|
isHeartbeatIdentityMismatch({ status: err.status, code: err.code, message: err.detail })) {
|
|
461
461
|
const tokenLabel = err.tokenAgentUid ?? "unknown";
|
|
462
|
-
const reason =
|
|
462
|
+
const reason = identityMismatchMessage("heartbeat", config.agentUid, tokenLabel);
|
|
463
463
|
setStatus({
|
|
464
464
|
lastHeartbeatOk: false,
|
|
465
465
|
lastHeartbeatError: reason.slice(0, 400),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CaptureContext } from "@sentry/node";
|
|
2
2
|
export declare const HEARTBEAT_IDENTITY_MISMATCH_CODE = "AGENT_IDENTITY_MISMATCH";
|
|
3
|
+
export declare function identityMismatchMessage(surface: "heartbeat" | "bot jobs", configuredAgentUid: string, tokenAgentUid?: string): string;
|
|
3
4
|
export type HeartbeatRunner = "agent-kit" | "bot";
|
|
4
5
|
export type HeartbeatAgentUidSource = "config_file" | "env" | "flag";
|
|
5
6
|
export type HeartbeatCredsSource = "explicit" | "default";
|
|
@@ -2,6 +2,11 @@ import { CLI_VERSION } from "../cli-version.js";
|
|
|
2
2
|
import { Sentry } from "../sentry.js";
|
|
3
3
|
import { peekIdToken } from "../utils/id-token.js";
|
|
4
4
|
export const HEARTBEAT_IDENTITY_MISMATCH_CODE = "AGENT_IDENTITY_MISMATCH";
|
|
5
|
+
export function identityMismatchMessage(surface, configuredAgentUid, tokenAgentUid) {
|
|
6
|
+
return (`${surface} stopped: identity mismatch configured agentUid=${configuredAgentUid} ` +
|
|
7
|
+
`token agentUid=${tokenAgentUid ?? "unknown"}; fix the bot config to use the token agentUid, ` +
|
|
8
|
+
`or re-mint credentials for the configured agentUid.`);
|
|
9
|
+
}
|
|
5
10
|
const AGENT_UID_RE = /^agt_[A-Za-z0-9_-]{1,100}$/;
|
|
6
11
|
function normalize(value) {
|
|
7
12
|
return (value ?? "").replace(/[^A-Za-z0-9]/g, "").toLowerCase();
|