@indigoai-us/hq-cli 5.345.180 → 5.345.182

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,13 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.345.182] — 2026-10-30
6
+ - Keep returning clients on the legacy engine until they update to the corrected cloud receiver, and preserve rename/delete convergence when switching sync engines.
7
+ - Local Grok bots now answer the first owner message normally after their welcome instead of introducing themselves again with `/help`.
8
+
9
+ ## [5.345.181] — 2026-10-30
10
+ - Local personal and company bots now share one HQ Fleet runtime installation while keeping isolated native profiles and gateway services. Existing local Fleet bots migrate in place without losing profile state.
11
+
5
12
  ## [5.345.180] — 2026-10-30
6
13
  - New `hq channels add <channel> <member...>` and `hq channels remove <channel> <member>`. An owner can now add a personal bot (or a teammate) to a channel from the CLI by @handle, email, or prs_/agt_ uid, so everyone in the channel can @mention it. Before this there was no verb for it, and posting "@bot" into the channel was refused with "No channel member matches". The server's join-first refusal and the owner-or-company-admin rule for adding and removing members are explained in plain words. Feedback e165b286-b059-4d5c-bd44-ac344f00c821.
7
14
  - A local bot can now have a model login of its own, so it no longer has to use yours. `hq bot login <name> [--runtime claude|codex]` runs the runtime's own sign-in into `~/.hq/bots/<name>/auth/<runtime>/` (`CLAUDE_CONFIG_DIR` or `CODEX_HOME`). `hq bot logout <name>` signs that login out and deletes the folder. `hq bot set <name> --account <id|default>` points the bot at an existing `hq capacity` account instead. Every model turn uses the chosen login. When that login is missing or its account is gone, the turn does not fall back to your login: the bot replies in the DM saying so, keeps the message pending, and `hq bot status` shows the problem. `hq bot status` now has a `login:` line (default, own, or the account name) and never shows a token.
@@ -57,7 +57,7 @@ import { runtimeDisplayName, signInCommand } from "../lib/bot/runtime-sign-in.js
57
57
  import { classifyRuntimeFailure, runtimeFailureReason } from "../lib/bot/runtime-failure.js";
58
58
  import { PROBE_DEFAULT_TIMEOUT_MS, probeBotRuntime } from "../lib/bot/probe.js";
59
59
  import { BOT_LOGIN_RUNTIMES, botAuthEnv, botRuntimeAuth, capacityAccountHome, describeBotAuth, formatBotAuth, isBotLoginRuntime, restoreBotSessions, setAsideBotSessions, signInBotRuntime, signOutBotRuntime, withRuntimeAuth, } from "../lib/bot/runtime-auth.js";
60
- import { BotApi, BotApiError, BOT_RESTORE_DEFAULTS, buildBotLocalConfig, describeBotLocalConfig, orphanBotRunMessage, parseBotLocalConfig, removeOrphanBotDaemon, botDaemonStatus, botDir, botCredsPath, botLogPath, botsRoot, botTokenStateDir, botWorkerRelDir, buildBotDaemonPaths, createBotLogger, deleteBotCreds, installBotDaemon, repairBotDaemonIfStale, healBotDaemonNodeFromJob, introDmText, isBotMemoryMode, botLocalMemoryDir, botMemoryMode, resolveBotMemoryDir, validateBotIntro, validateBotDisplayName, validateBotKickoff, validateBotEffort, validateBotModel, effectiveBotEffort, BOT_EFFORT_LEVELS, DEFAULT_BOT_EFFORT, BOT_MEMORY_MODES, BOT_KINDS, isBotKind, effectiveBotKind, effectiveBotCompanies, normalizeBotCompanies, SETUP_BOT_WORKER_ID, isBotRuntimeId, localNameForRemoteBot, remoteBotRunnability, isPidAlive, listBotWorkerOptions, patchBotConfig, readBotConfig, readBotCredsIdentity, readBotStatus, runtimeCrashSinceStart, resolveBotWorker, runBot, runtimeFor, scaffoldBotMemory, scaffoldBotWorker, startBotDaemon, stopBotDaemon, uninstallBotDaemon, validateBotName, writeBotConfig, writeBotCreds, BOT_RUNTIMES, BOT_INTRO_MAX_CHARS, BOT_DISPLAY_NAME_MAX_CHARS, BOT_KICKOFF_MAX_CHARS, detectBotPlatform, withBotLock, localBotRole, remoteBotRole, remoteBotDisplayName, personFacingName, writeCloudDisplayName, setupSlugFor, ASSISTANT_ROLE, HQ_FLEET_RUNTIME_ENGINE_ID, authenticateFleetLocalBot, bootstrapFleetLocalBot, buildSystemPrompt, controlFleetLocalBot, ensureFleetPython, fleetLocalGatewayPid, fleetProviderForRuntime, importFleetLocalMachineCredential, fleetProviderNeedsSignIn, fleetDefaultCompanies, fleetOwnerCompanies, fleetRuntimeIsDefault, refreshFleetLocalInstructions, fleetLocalPromotionRuntime, installPinnedFleetLocalDistribution, readPromptSources, removeFleetLocalBot, } from "../lib/bot/index.js";
60
+ import { BotApi, BotApiError, BOT_RESTORE_DEFAULTS, buildBotLocalConfig, describeBotLocalConfig, orphanBotRunMessage, parseBotLocalConfig, removeOrphanBotDaemon, botDaemonStatus, botDir, botCredsPath, botLogPath, botsRoot, botTokenStateDir, botWorkerRelDir, buildBotDaemonPaths, createBotLogger, deleteBotCreds, installBotDaemon, repairBotDaemonIfStale, healBotDaemonNodeFromJob, introDmText, isBotMemoryMode, botLocalMemoryDir, botMemoryMode, resolveBotMemoryDir, validateBotIntro, validateBotDisplayName, validateBotKickoff, validateBotEffort, validateBotModel, effectiveBotEffort, BOT_EFFORT_LEVELS, DEFAULT_BOT_EFFORT, BOT_MEMORY_MODES, BOT_KINDS, isBotKind, effectiveBotKind, effectiveBotCompanies, normalizeBotCompanies, SETUP_BOT_WORKER_ID, isBotRuntimeId, localNameForRemoteBot, remoteBotRunnability, isPidAlive, listBotWorkerOptions, patchBotConfig, readBotConfig, readBotCredsIdentity, readBotStatus, runtimeCrashSinceStart, resolveBotWorker, runBot, runtimeFor, scaffoldBotMemory, scaffoldBotWorker, startBotDaemon, stopBotDaemon, uninstallBotDaemon, validateBotName, writeBotConfig, writeBotCreds, BOT_RUNTIMES, BOT_INTRO_MAX_CHARS, BOT_DISPLAY_NAME_MAX_CHARS, BOT_KICKOFF_MAX_CHARS, detectBotPlatform, withBotLock, localBotRole, remoteBotRole, remoteBotDisplayName, personFacingName, writeCloudDisplayName, setupSlugFor, ASSISTANT_ROLE, HQ_FLEET_RUNTIME_ENGINE_ID, authenticateFleetLocalBot, bootstrapFleetLocalBot, buildSystemPrompt, controlFleetLocalBot, ensureFleetPython, fleetLocalGatewayPid, fleetLocalProfileNeedsAdoption, fleetProviderForRuntime, importFleetLocalMachineCredential, fleetProviderNeedsSignIn, fleetDefaultCompanies, fleetOwnerCompanies, fleetRuntimeIsDefault, refreshFleetLocalInstructions, fleetLocalPromotionRuntime, installPinnedFleetLocalDistribution, readPromptSources, removeFleetLocalBot, } from "../lib/bot/index.js";
61
61
  function collectRepeated(value, previous) {
62
62
  return [...previous, value];
63
63
  }
@@ -153,7 +153,7 @@ function fleetAuthCommand(name, config) {
153
153
  return `hq bot auth ${name} --provider ${config.runtime === "grok" ? "grok" : config.runtime === "codex" ? "chatgpt" : "claude"}`;
154
154
  }
155
155
  function runFleetRuntimeControl(name, config, action, json) {
156
- if ((action === "start" || action === "restart") && config.fleetAuthPending === true) {
156
+ if ((action === "install" || action === "start" || action === "restart") && config.fleetAuthPending === true) {
157
157
  const authCommand = fleetAuthCommand(name, config);
158
158
  if (json)
159
159
  console.log(JSON.stringify({ ok: false, name, running: false, state: "stopped", needsSignIn: true, authCommand }, null, 2));
@@ -161,10 +161,10 @@ function runFleetRuntimeControl(name, config, action, json) {
161
161
  throw Object.assign(new Error(`Sign this bot in first: ${authCommand}`), { expected: true });
162
162
  return;
163
163
  }
164
- if (action === "start" || action === "restart") {
164
+ if (action === "install" || action === "start" || action === "restart") {
165
165
  refreshFleetLocalInstructions(config.agentUid, fleetBotSystemPrompt(name, config));
166
166
  }
167
- const installService = config.fleetServiceInstallPending === true && (action === "start" || action === "restart");
167
+ const installService = action === "install" || (config.fleetServiceInstallPending === true && (action === "start" || action === "restart"));
168
168
  const result = controlFleetLocalBot(config.agentUid, installService ? "install" : action);
169
169
  if (installService && result.ok)
170
170
  patchBotConfig(botDir(name), { fleetServiceInstallPending: false, enabled: true });
@@ -434,10 +434,11 @@ async function startFleetRuntimeBot(name, dir, config, output, extra) {
434
434
  throw Object.assign(new Error(`Sign this bot in first: ${authCommand}`), { expected: true });
435
435
  return { running: false, how: "waiting for sign-in" };
436
436
  }
437
+ const adopted = await adoptFleetRuntimeProfile(name, dir, config);
437
438
  refreshFleetLocalInstructions(config.agentUid, fleetBotSystemPrompt(name, config));
438
439
  const before = readBotStatus(dir);
439
440
  const alreadyRunning = !!before && before.state === "running" && isPidAlive(before.pid);
440
- const installService = config.fleetServiceInstallPending === true;
441
+ const installService = adopted || config.fleetServiceInstallPending === true;
441
442
  const result = controlFleetLocalBot(config.agentUid, installService ? "install" : alreadyRunning ? "restart" : "start");
442
443
  if (installService && result.ok)
443
444
  patchBotConfig(dir, { fleetServiceInstallPending: false, enabled: true });
@@ -459,6 +460,29 @@ async function startFleetRuntimeBot(name, dir, config, output, extra) {
459
460
  console.log(chalk.yellow(`${name} did not report running within 45s`) + chalk.dim(` logs: ~/.hq-fleet/profiles/${config.agentUid}/logs`));
460
461
  return { running, how };
461
462
  }
463
+ async function adoptFleetRuntimeProfile(name, dir, config) {
464
+ if (!fleetLocalProfileNeedsAdoption(config.agentUid))
465
+ return false;
466
+ const installation = await installPinnedFleetLocalDistribution();
467
+ const python = await ensureFleetPython();
468
+ const companyScope = effectiveBotKind(config) === "company"
469
+ ? effectiveBotCompanies(config)
470
+ : await fleetOwnerCompanies();
471
+ await bootstrapFleetLocalBot({
472
+ agentUid: config.agentUid,
473
+ ownerUid: config.ownerUid,
474
+ hqRoot: config.hqRoot,
475
+ botDir: dir,
476
+ installation,
477
+ systemPrompt: fleetBotSystemPrompt(name, config),
478
+ provider: fleetProviderForRuntime(config.runtime, config.model),
479
+ ownerCompanies: companyScope,
480
+ }, { python, start: false });
481
+ const credentials = botCredsPath(dir);
482
+ if (fs.existsSync(credentials))
483
+ importFleetLocalMachineCredential(config.agentUid, credentials);
484
+ return true;
485
+ }
462
486
  /**
463
487
  * `output`: "json" | "text" print a result; "silent" prints nothing — used
464
488
  * when stop is a step inside rm/restart, whose own JSON must be the only
@@ -2073,7 +2097,8 @@ export function botExists(name) {
2073
2097
  export async function runBotRestart(nameArg, opts = {}) {
2074
2098
  const b = requireBot(nameArg);
2075
2099
  if (isFleetRuntimeBot(b.config)) {
2076
- runFleetRuntimeControl(b.name, b.config, "restart", opts.json === true || opts.output === "json");
2100
+ const adopted = await adoptFleetRuntimeProfile(b.name, b.dir, b.config);
2101
+ runFleetRuntimeControl(b.name, b.config, adopted ? "install" : "restart", opts.json === true || opts.output === "json");
2077
2102
  return;
2078
2103
  }
2079
2104
  const running = readBotStatus(b.dir);
@@ -2094,10 +2119,11 @@ async function runBotAuth(nameArg, opts) {
2094
2119
  if (opts.apiKey && !apiKey) {
2095
2120
  throw Object.assign(new Error("No API key was received on stdin."), { expected: true });
2096
2121
  }
2122
+ const adopted = await adoptFleetRuntimeProfile(b.name, b.dir, b.config);
2097
2123
  const result = authenticateFleetLocalBot({
2098
2124
  agentUid: b.config.agentUid,
2099
2125
  provider: opts.provider,
2100
- ...(b.config.fleetAuthPending === true ? { installService: true } : {}),
2126
+ ...(adopted || b.config.fleetAuthPending === true ? { installService: true } : {}),
2101
2127
  ...(opts.model ? { model: opts.model } : {}),
2102
2128
  ...(apiKey ? { apiKey } : {}),
2103
2129
  ...(opts.baseUrl ? { baseUrl: opts.baseUrl } : {}),
@@ -2529,8 +2555,9 @@ async function repairLocalBot(name, api, bot, daemon) {
2529
2555
  });
2530
2556
  createBotLogger(dir)("info", `re-issued machine credentials for ${name} (${bot.agentUid}) on ${localMachineId()}`);
2531
2557
  if (isFleetRuntimeBot(config)) {
2558
+ const adopted = await adoptFleetRuntimeProfile(name, dir, config);
2532
2559
  importFleetLocalMachineCredential(bot.agentUid, botCredsPath(dir));
2533
- const restarted = controlFleetLocalBot(bot.agentUid, "restart").ok === true;
2560
+ const restarted = controlFleetLocalBot(bot.agentUid, adopted ? "install" : "restart").ok === true;
2534
2561
  return restarted ? "new credentials, HQ Fleet Runtime restarted" : "new credentials; the HQ Fleet Runtime did not restart (hq bot start " + name + ")";
2535
2562
  }
2536
2563
  if (daemon && process.platform === "darwin") {
@@ -2782,7 +2809,8 @@ export function registerBotCommand(program) {
2782
2809
  .action((name, opts) => wrap(async () => {
2783
2810
  const b = requireBot(name);
2784
2811
  if (isFleetRuntimeBot(b.config)) {
2785
- runFleetRuntimeControl(b.name, b.config, "start", opts.json === true);
2812
+ const adopted = await adoptFleetRuntimeProfile(b.name, b.dir, b.config);
2813
+ runFleetRuntimeControl(b.name, b.config, adopted ? "install" : "start", opts.json === true);
2786
2814
  return;
2787
2815
  }
2788
2816
  await startBot(b.name, b.dir, b.config, opts.json ? "json" : "text");