@indigoai-us/hq-cli 5.345.197 → 5.345.199

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 (118) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/dist/command-catalog.generated.d.ts +393 -12
  3. package/dist/command-catalog.generated.js +482 -12
  4. package/dist/commands/bot-events.d.ts +19 -0
  5. package/dist/commands/bot-events.js +46 -0
  6. package/dist/commands/bot-jobs.d.ts +2 -0
  7. package/dist/commands/bot-jobs.js +43 -2
  8. package/dist/commands/bot.d.ts +5 -0
  9. package/dist/commands/bot.js +33 -1
  10. package/dist/commands/core-resolve-company-native.d.ts +2 -1
  11. package/dist/commands/core-resolve-company-native.js +2 -24
  12. package/dist/commands/deploy-domains.d.ts +14 -2
  13. package/dist/commands/deploy-domains.js +726 -42
  14. package/dist/commands/integrations-connect.js +41 -3
  15. package/dist/commands/lanes-report.d.ts +2 -1
  16. package/dist/commands/lanes-report.js +44 -1
  17. package/dist/commands/lanes.d.ts +9 -0
  18. package/dist/commands/lanes.js +95 -9
  19. package/dist/commands/meetings.js +1 -21
  20. package/dist/commands/secrets.js +27 -6
  21. package/dist/commands/signals-run.d.ts +2 -0
  22. package/dist/commands/signals-run.js +6 -1
  23. package/dist/lanes-drain-hook.js +9 -0
  24. package/dist/lib/bot/api.d.ts +5 -0
  25. package/dist/lib/bot/claude-login.d.ts +31 -0
  26. package/dist/lib/bot/claude-login.js +160 -0
  27. package/dist/lib/bot/company-bind.d.ts +34 -0
  28. package/dist/lib/bot/company-bind.js +112 -0
  29. package/dist/lib/bot/config.js +3 -1
  30. package/dist/lib/bot/events.d.ts +18 -0
  31. package/dist/lib/bot/events.js +160 -0
  32. package/dist/lib/bot/executive-settings.d.ts +10 -0
  33. package/dist/lib/bot/executive-settings.js +43 -0
  34. package/dist/lib/bot/fleet-cron.js +4 -0
  35. package/dist/lib/bot/fleet-local.d.ts +12 -0
  36. package/dist/lib/bot/fleet-local.js +50 -20
  37. package/dist/lib/bot/job-run.js +1 -1
  38. package/dist/lib/bot/jobs/hot-signal-sync.d.ts +8 -0
  39. package/dist/lib/bot/jobs/hot-signal-sync.js +2 -0
  40. package/dist/lib/bot/jobs/meeting-detect.d.ts +28 -0
  41. package/dist/lib/bot/jobs/meeting-detect.js +176 -0
  42. package/dist/lib/bot/jobs/meeting-rider.d.ts +53 -0
  43. package/dist/lib/bot/jobs/meeting-rider.js +284 -0
  44. package/dist/lib/bot/jobs/signal-to-lane.d.ts +32 -0
  45. package/dist/lib/bot/jobs/signal-to-lane.js +169 -0
  46. package/dist/lib/bot/local-jobs.d.ts +15 -2
  47. package/dist/lib/bot/local-jobs.js +24 -7
  48. package/dist/lib/bot/run.d.ts +7 -49
  49. package/dist/lib/bot/run.js +135 -12
  50. package/dist/lib/bot/session.d.ts +19 -1
  51. package/dist/lib/bot/session.js +75 -28
  52. package/dist/lib/bot/status.d.ts +21 -0
  53. package/dist/lib/core-utils/manifest-slugs.d.ts +2 -0
  54. package/dist/lib/core-utils/manifest-slugs.js +26 -0
  55. package/dist/lib/doctor/checks/bots.d.ts +6 -0
  56. package/dist/lib/doctor/checks/bots.js +47 -1
  57. package/dist/lib/hot-channels/adapters/meetings.d.ts +1 -0
  58. package/dist/lib/hot-channels/adapters/meetings.js +3 -1
  59. package/dist/lib/hot-channels/meeting-source-ref.d.ts +3 -0
  60. package/dist/lib/hot-channels/meeting-source-ref.js +7 -0
  61. package/dist/lib/hot-channels/schedule.js +2 -2
  62. package/dist/lib/hot-channels/signals-pass.d.ts +9 -32
  63. package/dist/lib/hot-channels/signals-pass.js +51 -17
  64. package/dist/lib/lanes/admission.d.ts +2 -0
  65. package/dist/lib/lanes/admission.js +4 -0
  66. package/dist/lib/lanes/approval-gate.js +4 -1
  67. package/dist/lib/lanes/links.d.ts +8 -1
  68. package/dist/lib/lanes/links.js +84 -3
  69. package/dist/lib/lanes/outcome.d.ts +154 -0
  70. package/dist/lib/lanes/outcome.js +151 -0
  71. package/dist/lib/lanes/reconcile.js +1 -0
  72. package/dist/lib/lanes/signal-brief-template.d.ts +7 -0
  73. package/dist/lib/lanes/signal-brief-template.js +40 -0
  74. package/dist/lib/lanes/signal-lane.d.ts +24 -0
  75. package/dist/lib/lanes/signal-lane.js +99 -0
  76. package/dist/lib/lanes/source-report.d.ts +37 -0
  77. package/dist/lib/lanes/source-report.js +66 -0
  78. package/dist/lib/lanes/spawn.d.ts +6 -0
  79. package/dist/lib/lanes/spawn.js +21 -0
  80. package/dist/lib/lanes/store.d.ts +3 -0
  81. package/dist/lib/lanes/store.js +64 -0
  82. package/dist/lib/lanes/story-ledger.d.ts +3 -0
  83. package/dist/lib/lanes/story-ledger.js +1 -0
  84. package/dist/lib/lanes/types.d.ts +137 -0
  85. package/dist/lib/lanes/types.js +17 -2
  86. package/dist/lib/lanes/watcher.js +4 -0
  87. package/dist/lib/live-meetings.d.ts +19 -0
  88. package/dist/lib/live-meetings.js +23 -0
  89. package/dist/lib/mesh/live/daemon/doctor.js +6 -7
  90. package/dist/lib/mesh/live/spool.d.ts +8 -0
  91. package/dist/lib/mesh/live/spool.js +59 -40
  92. package/dist/lib/plan-limit-nag.d.ts +30 -4
  93. package/dist/lib/plan-limit-nag.js +68 -17
  94. package/dist/lib/signals/engine.d.ts +4 -0
  95. package/dist/lib/signals/engine.js +25 -5
  96. package/dist/lib/signals/incremental.d.ts +42 -0
  97. package/dist/lib/signals/incremental.js +191 -0
  98. package/dist/lib/signals/prior-signals.d.ts +11 -0
  99. package/dist/lib/signals/prior-signals.js +44 -0
  100. package/dist/lib/signals/reply.js +6 -1
  101. package/dist/lib/signals/settings.d.ts +5 -0
  102. package/dist/lib/signals/settings.js +17 -0
  103. package/dist/lib/signals/steps/extract.d.ts +30 -2
  104. package/dist/lib/signals/steps/extract.js +153 -11
  105. package/dist/lib/signals/steps/types.d.ts +1 -0
  106. package/dist/lib/signals/write-guard.js +7 -0
  107. package/dist/secrets-env-action.d.ts +70 -0
  108. package/dist/secrets-env-action.js +220 -2
  109. package/dist/utils/cognito-callback-port.d.ts +15 -0
  110. package/dist/utils/cognito-callback-port.js +51 -0
  111. package/dist/utils/cognito-config.js +2 -3
  112. package/dist/utils/cognito-session.d.ts +7 -6
  113. package/dist/utils/cognito-session.js +14 -14
  114. package/dist/utils/interactive-caller.d.ts +15 -0
  115. package/dist/utils/interactive-caller.js +70 -0
  116. package/dist/utils/login-browser.js +3 -1
  117. package/dist/utils/resident-package-preload.js +4 -0
  118. package/package.json +9 -7
@@ -114,6 +114,8 @@ export interface BotJobsOptions {
114
114
  add?: string;
115
115
  every?: string;
116
116
  cron?: string;
117
+ on?: string;
118
+ filter?: string[];
117
119
  tz?: string;
118
120
  rm?: string;
119
121
  /** Change an existing job's schedule, keeping its id, instruction and history. */
@@ -16,7 +16,7 @@
16
16
  * back when it checks what is due.
17
17
  */
18
18
  import chalk from "chalk";
19
- import { localJobsClient } from "../lib/bot/local-jobs.js";
19
+ import { addLocalJob, localJobsClient, readLocalJobs, toJobRecord } from "../lib/bot/local-jobs.js";
20
20
  import { BotApiError } from "../lib/bot/api.js";
21
21
  import { effectiveBotKind, HQ_FLEET_RUNTIME_ENGINE_ID } from "../lib/bot/config.js";
22
22
  import { fleetCronOps, fleetOwnerOrigin, fleetScheduleFromLegacy } from "../lib/bot/fleet-cron.js";
@@ -318,6 +318,10 @@ export function fleetJobsClient(config, ops, timezone) {
318
318
  // ─── Reading jobs back ───────────────────────────────────────────────────────
319
319
  /** A schedule in plain words, falling back to the raw expression. */
320
320
  export function describeSchedule(job) {
321
+ if (job.trigger) {
322
+ const filters = Object.entries(job.trigger.filter ?? {}).map(([key, value]) => `${key}=${value}`).join(", ");
323
+ return `on ${job.trigger.event}${filters ? ` (${filters})` : ""}`;
324
+ }
321
325
  const schedule = job.schedule;
322
326
  if (!schedule)
323
327
  return "on a schedule";
@@ -391,7 +395,7 @@ export function formatJobsList(botName, jobs, showQuietOption = false) {
391
395
  lines.push(` runs ${describeSchedule(job)}`);
392
396
  if (showQuietOption && isQuietJobContext(job.context))
393
397
  lines.push(" delivery: quiet after successful runs");
394
- lines.push(` next run: ${job.nextRunAt ? `${utcMinute(job.nextRunAt)} UTC` : "not scheduled yet"}`);
398
+ lines.push(` next run: ${job.trigger ? "when a matching event arrives" : job.nextRunAt ? `${utcMinute(job.nextRunAt)} UTC` : "not scheduled yet"}`);
395
399
  lines.push(` last run: ${describeLastRun(job)}`);
396
400
  }
397
401
  return lines.join("\n");
@@ -454,6 +458,11 @@ export async function runBotJobs(nameArg, opts, deps) {
454
458
  if (opts.quiet && opts.add === undefined) {
455
459
  refuse("Use --quiet with --add to set a scheduled job's delivery option.");
456
460
  }
461
+ if (opts.on !== undefined && (opts.add === undefined || opts.every !== undefined || opts.cron !== undefined || opts.tz !== undefined)) {
462
+ refuse("Use --on with --add and without --every, --cron, or --tz.");
463
+ }
464
+ if (opts.filter?.length && opts.on === undefined)
465
+ refuse("Use --filter with --on.");
457
466
  // Shared by --add and --reschedule: one schedule from --every or --cron, in
458
467
  // the stored form, held to the same floor.
459
468
  const scheduleFromOptions = () => {
@@ -516,6 +525,36 @@ export async function runBotJobs(nameArg, opts, deps) {
516
525
  if (opts.quiet && !(await quietOptionEnabled())) {
517
526
  refuse(`--quiet requires the ${BOT_JOB_QUIET_OPTION_FLAG} flag, which is currently disabled.`);
518
527
  }
528
+ if (opts.on !== undefined) {
529
+ if (fleet)
530
+ refuse("Event jobs require a local CLI bot; HQ Fleet Runtime does not drain this event journal.");
531
+ const event = opts.on.trim();
532
+ if (!event || event.length > 256 || /[\r\n]/.test(event))
533
+ refuse("Event name must be 1–256 characters without newlines.");
534
+ const prompt = opts.add.trim();
535
+ if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES)
536
+ refuse("Job instruction must be non-empty and at most 16 KB.");
537
+ const filter = Object.create(null);
538
+ for (const entry of opts.filter ?? []) {
539
+ const split = entry.indexOf("=");
540
+ if (split < 1 || !entry.slice(0, split).trim())
541
+ refuse("Each --filter must be key=value.");
542
+ const key = entry.slice(0, split).trim();
543
+ if (Object.hasOwn(filter, key))
544
+ refuse(`Duplicate filter key: ${key}`);
545
+ filter[key] = entry.slice(split + 1);
546
+ }
547
+ if (readLocalJobs(dir).length >= MAX_ACTIVE_JOBS_PER_AGENT)
548
+ refuse(`${name} already has the maximum of ${MAX_ACTIVE_JOBS_PER_AGENT} jobs. Remove one first.`);
549
+ const created = toJobRecord(addLocalJob(dir, {
550
+ prompt,
551
+ timezone: localZone,
552
+ trigger: { kind: "event", event, ...(Object.keys(filter).length ? { filter } : {}) },
553
+ ...(opts.quiet ? { context: { [JOB_RUN_OPTIONS_CONTEXT_KEY]: { quiet: true } } } : {}),
554
+ }));
555
+ out(opts.json ? JSON.stringify({ ok: true, job: created }, null, 2) : `Added ${created.jobId}: ${name} runs it ${describeSchedule(created)}.`);
556
+ return;
557
+ }
519
558
  const schedule = scheduleFromOptions();
520
559
  const body = buildCreateJobBody({ prompt: opts.add, cron: schedule.cron, timezone: schedule.timezone, quiet: opts.quiet });
521
560
  const api = await jobsApi();
@@ -558,6 +597,8 @@ export function registerBotJobsCommand(bot, deps) {
558
597
  .option("--add <what>", "Schedule new work, in plain language")
559
598
  .option("--every <when>", 'How often, in plain language (e.g. "every weekday at 9am")')
560
599
  .option("--cron <expr>", 'How often, as a cron expression (e.g. "0 9 * * 1-5")')
600
+ .option("--on <event>", "Run when this event is emitted")
601
+ .option("--filter <key=value>", "Match an event payload field (repeatable)", (value, values) => [...values, value], [])
561
602
  .option("--tz <zone>", "IANA timezone for the schedule (default: this computer's)")
562
603
  .option("--quiet", "Skip owner DMs after successful runs (requires rollout flag)")
563
604
  .option("--rm <jobId>", "Remove a scheduled job")
@@ -1,5 +1,6 @@
1
1
  import { Command } from "commander";
2
2
  import { type RuntimeSignInCheck, type RuntimeSignInIssue } from "../lib/bot/runtime-sign-in.js";
3
+ import { type ClaudeLoginCheck } from "../lib/bot/claude-login.js";
3
4
  import type { BotStatusFile } from "../lib/bot/status.js";
4
5
  import { probeBotRuntime, type RuntimeProbeResult } from "../lib/bot/probe.js";
5
6
  import { type SpawnInteractive } from "../lib/bot/runtime-auth.js";
@@ -115,6 +116,10 @@ export declare function spawnDetachedRun(name: string, dir: string): number;
115
116
  * "unreadable output: trailing characters").
116
117
  */
117
118
  /** Seams for the self-stop path, replaced in tests. */
119
+ export declare const botCreateSeams: {
120
+ /** The Claude Code login read the way the HQ Fleet Runtime reads it. */
121
+ claudeLogin: () => ClaudeLoginCheck;
122
+ };
118
123
  export declare const botStopSeams: {
119
124
  /** True when this process runs inside the bot process `botPid` (one of its turns). */
120
125
  isInsideBot: (botPid: number) => boolean;
@@ -43,6 +43,8 @@ import { createVaultObjectDownloader } from "../lib/agent-kit/attachment-downloa
43
43
  import { addBotToCompanies, describeCompanyFailures, removeBotFromCompanies } from "./bot-companies.js";
44
44
  import { registerBotContinuityCommand } from "./bot-continuity.js";
45
45
  import { registerBotJobsCommand } from "./bot-jobs.js";
46
+ import { registerBotEventsCommand } from "./bot-events.js";
47
+ import { executiveStatus } from "../lib/bot/executive-settings.js";
46
48
  import { ensureFleetHotSignalSync, fleetCronOps, migrateLegacyJobsToFleet } from "../lib/bot/fleet-cron.js";
47
49
  import { resolvePackSetupPrompt } from "../lib/bot/pack-setup.js";
48
50
  import { detectCodingToolActivity } from "../lib/bot/coding-tool-activity.js";
@@ -63,6 +65,8 @@ import { daemonPaths } from "../lib/daemon/paths.js";
63
65
  import { launchdLabel } from "../lib/bot/paths.js";
64
66
  import { isAncestorProcess } from "../lib/bot/self-process.js";
65
67
  import { runtimeDisplayName, signInCommand } from "../lib/bot/runtime-sign-in.js";
68
+ import { checkClaudeCodeLogin, claudeLoginFix, describeClaudeLoginSources } from "../lib/bot/claude-login.js";
69
+ import { unresolvedLastFailure } from "../lib/doctor/checks/bots.js";
66
70
  import { classifyRuntimeFailure, runtimeFailureReason } from "../lib/bot/runtime-failure.js";
67
71
  import { PROBE_DEFAULT_TIMEOUT_MS, probeBotRuntime } from "../lib/bot/probe.js";
68
72
  import { BOT_LOGIN_RUNTIMES, botAuthEnv, botRuntimeAuth, capacityAccountHome, describeBotAuth, formatBotAuth, isBotLoginRuntime, restoreBotSessions, setAsideBotSessions, signInBotRuntime, signOutBotRuntime, withRuntimeAuth, } from "../lib/bot/runtime-auth.js";
@@ -774,6 +778,22 @@ async function installFleetRuntimeProfile(name, dir, config, opts = {}) {
774
778
  * "unreadable output: trailing characters").
775
779
  */
776
780
  /** Seams for the self-stop path, replaced in tests. */
781
+ export const botCreateSeams = {
782
+ /** The Claude Code login read the way the HQ Fleet Runtime reads it. */
783
+ claudeLogin: () => checkClaudeCodeLogin(),
784
+ };
785
+ /**
786
+ * A Claude bot on the HQ Fleet Runtime answers with the owner's Claude Code
787
+ * login. Creating one on a computer with no readable login provisions an
788
+ * identity that can only ever answer "I'm away for a bit", so refuse first
789
+ * and say which sources were checked.
790
+ */
791
+ function requireClaudeCodeLoginForCreate(name) {
792
+ const check = botCreateSeams.claudeLogin();
793
+ if (check.signedIn)
794
+ return;
795
+ throw Object.assign(new Error(`Claude Code is not signed in on this computer, so ${name} could not answer. ${describeClaudeLoginSources(check)} ${claudeLoginFix()}`.replace(/\s+/g, " ").trim()), { expected: true });
796
+ }
777
797
  export const botStopSeams = {
778
798
  /** True when this process runs inside the bot process `botPid` (one of its turns). */
779
799
  isInsideBot: (botPid) => isAncestorProcess(botPid),
@@ -1114,6 +1134,8 @@ async function runBotCreateLocked(name, opts) {
1114
1134
  }
1115
1135
  const fleetProvider = fleetProviderForRuntime(runtime, model);
1116
1136
  const fleetAuthPending = fleetProviderNeedsSignIn(fleetProvider);
1137
+ if (fleetProvider.id === "anthropic")
1138
+ requireClaudeCodeLoginForCreate(name);
1117
1139
  const token = await ownerToken();
1118
1140
  const owner = await resolveCallerPersonUid(token, undefined, { command: "hq bot create" });
1119
1141
  if (!owner)
@@ -1664,7 +1686,7 @@ async function runBotStatus(nameArg, opts) {
1664
1686
  const creds = readBotCredsIdentity(dir);
1665
1687
  const channels = fleet ? fleetLocalChannels(readFleetLocalGatewayState(config.agentUid), row.processAlive) : null;
1666
1688
  if (opts.json) {
1667
- console.log(JSON.stringify({ ...row, ...(fleet ? { engine: config.engine, channels } : {}), credsPresent: fleet || !!creds, login: describeBotAuth(dir, config), status }, null, 2));
1689
+ console.log(JSON.stringify({ ...row, executive: executiveStatus(config, dir), ...(fleet ? { engine: config.engine, channels } : {}), credsPresent: fleet || !!creds, login: describeBotAuth(dir, config), status }, null, 2));
1668
1690
  return;
1669
1691
  }
1670
1692
  console.log(`${chalk.bold(name)} ${row.agentUid}`);
@@ -1733,6 +1755,15 @@ async function runBotStatus(nameArg, opts) {
1733
1755
  const cls = classifyRuntimeFailure(status.lastError);
1734
1756
  console.log(` last problem: ${chalk.yellow(`${cls}: ${runtimeFailureReason(cls, row.runtime)}`)} ${chalk.dim(`(details: hq bot logs ${name})`)}`);
1735
1757
  }
1758
+ if (status.lastFailure) {
1759
+ const failure = status.lastFailure;
1760
+ const resolved = unresolvedLastFailure(status) === null;
1761
+ const paint = resolved ? chalk.dim : chalk.yellow;
1762
+ console.log(` last failure: ${paint(`${failure.at} (${failure.class}${resolved ? ", answered since" : ""})`)}`);
1763
+ console.log(` cause: ${paint(failure.cause)}`);
1764
+ console.log(` fix: ${paint(failure.fix)}`);
1765
+ console.log(` report: ${failure.uploaded && failure.reportId ? `${failure.reportId} (in HQ, with the bot's last log lines)` : chalk.red("not uploaded to HQ")} ${chalk.dim(`owner DM ${failure.ownerNotified ? "sent" : "not sent"}`)}`);
1766
+ }
1736
1767
  }
1737
1768
  console.log(chalk.dim(` state dir: ${dir}`));
1738
1769
  }
@@ -3052,6 +3083,7 @@ export function registerBotCommand(program) {
3052
3083
  .description("Personal local bots that run on this computer with your own model login");
3053
3084
  registerBotContinuityCommand(bot);
3054
3085
  registerBotJobsCommand(bot, { requireBot, botTokenSupplier });
3086
+ registerBotEventsCommand(bot, { requireBot });
3055
3087
  bot.command("promote <name>")
3056
3088
  .description("Move this local bot to cloud compute, preserving its identity and private context")
3057
3089
  .requiredOption("--company <uid>", "Destination company identity")
@@ -1,4 +1,6 @@
1
1
  import * as fs from "node:fs";
2
+ import { parseManifestSlugs } from "../lib/core-utils/manifest-slugs.js";
3
+ export { parseManifestSlugs };
2
4
  export declare const RESOLVE_COMPANY_ASSET = "core/scripts/resolve-company.sh";
3
5
  export declare const RESOLVE_COMPANY_HELP: string;
4
6
  export type ResolveCompanyResult = {
@@ -27,5 +29,4 @@ export type ResolveCompanyDependencies = {
27
29
  };
28
30
  export declare function resolveCompany(args: readonly string[], dependencies: ResolveCompanyDependencies): Promise<ResolveCompanyResult>;
29
31
  export declare function runResolveCompanyFast(args: readonly string[], stdin: string, cwd: string, hqRoot: string | undefined, _commandName?: string, _hqRootArg?: string, stdinReader?: () => Promise<string>): Promise<number>;
30
- export {};
31
32
  //# sourceMappingURL=core-resolve-company-native.d.ts.map
@@ -4,7 +4,9 @@ import * as fs from "node:fs";
4
4
  import * as path from "node:path";
5
5
  import { awkCannotOpenFileDiagnostic } from "../lib/core-utils/awk-diagnostics.js";
6
6
  import { buildCmdExeSpawnPlan, isWindowsBatchFile } from "../utils/windows-spawn.js";
7
+ import { parseManifestSlugs } from "../lib/core-utils/manifest-slugs.js";
7
8
  import { fastFlagEnabledDefaultOn } from "../native-fast-route.js";
9
+ export { parseManifestSlugs };
8
10
  export const RESOLVE_COMPANY_ASSET = "core/scripts/resolve-company.sh";
9
11
  export const RESOLVE_COMPANY_HELP = [
10
12
  "hq-core: public",
@@ -29,7 +31,6 @@ export const RESOLVE_COMPANY_HELP = [
29
31
  "ROOT=\"\"",
30
32
  ].join("\n") + "\n";
31
33
  const EMPTY_ENV = {};
32
- const keepSlug = (slug) => slug !== "" && slug !== "_template" && slug !== "companies" && slug !== "unaffiliated_repos";
33
34
  function errorCode(error) {
34
35
  return error && typeof error === "object" && "code" in error && typeof error.code === "string"
35
36
  ? error.code
@@ -75,29 +76,6 @@ function isFile(filePath, fileSystem) {
75
76
  throw error;
76
77
  }
77
78
  }
78
- function parseManifestSlugs(text) {
79
- const slugs = new Set();
80
- let wrapped = false;
81
- for (const rawLine of text.split("\n")) {
82
- const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
83
- if (/^companies:[ \t]*$/.test(line)) {
84
- wrapped = true;
85
- continue;
86
- }
87
- if (wrapped && /^[^ \t][^:]*:[ \t]*$/.test(line))
88
- wrapped = false;
89
- if (wrapped) {
90
- const match = line.match(/^ {2}([A-Za-z][A-Za-z0-9_-]*):/);
91
- if (match && keepSlug(match[1]))
92
- slugs.add(match[1]);
93
- continue;
94
- }
95
- const match = line.match(/^([A-Za-z][A-Za-z0-9_-]*):/);
96
- if (match && keepSlug(match[1]))
97
- slugs.add(match[1]);
98
- }
99
- return [...slugs];
100
- }
101
79
  function promptSlug(prompt, slugs) {
102
80
  if (!prompt)
103
81
  return "";
@@ -43,8 +43,12 @@ export declare function addOnConfirmQuestion(domain: string, environment: string
43
43
  appLabel: string;
44
44
  orgSlug: string;
45
45
  }, pricing: Record<string, unknown> | null): string;
46
- /** Shown in the buy prompt when GET /v1/pricing does not answer. */
47
- export declare const PURCHASE_TERMS_UNAVAILABLE = "The renewal and refund terms could not be loaded. Check them on the HQ pricing page before you buy.";
46
+ /** Shown in the buy prompt when neither search nor GET /v1/pricing names a renewal price. */
47
+ export declare const PURCHASE_TERMS_UNAVAILABLE = "The renewal price could not be loaded. Run 'hq deploy domains search' and check the renewal price before you buy.";
48
+ /** Sandbox label. Every search and buy surface prints this when the server says testMode. */
49
+ export declare const TEST_MODE_LABEL = "Test mode: sandbox prices. Nothing real is registered or charged.";
50
+ export declare const TRANSFER_LOCK_NOTICE = "Domains cannot be transferred to another registrar for 60 days after purchase.";
51
+ export declare const PURCHASES_ARE_FINAL = "Purchases are final.";
48
52
  /** The purchase terms published as usage.domains.purchase. Null when not published. */
49
53
  export declare function purchaseTermsLine(pricing: Record<string, unknown> | null): string | null;
50
54
  /** Hard deadline for `base status --wait`, so a script never waits forever. */
@@ -68,6 +72,14 @@ export declare function baseDomainPriceLine(body: {
68
72
  /** The approval question for `base add`, before the server says the basis. */
69
73
  export declare function baseAddConfirmQuestion(domain: string, orgSlug: string, pricing: Record<string, unknown> | null): string;
70
74
  export declare function parsePrice(raw: string): number;
75
+ interface PurchaseUse {
76
+ kind: "app" | "base" | "hold";
77
+ appId?: string;
78
+ }
79
+ /** What the purchase is for. `app:<id>` attaches to that deployment, `base` is the company domain, `hold` registers only. */
80
+ export declare function parseUse(raw: string): PurchaseUse;
81
+ /** Hosting tier, separate from the registrar price. Hold is register-only. */
82
+ export declare function hostingTierLine(use: PurchaseUse, pricing: Record<string, unknown> | null): string;
71
83
  export declare function registerDeployDomainsCommand(deploy: Command): void;
72
84
  export {};
73
85
  //# sourceMappingURL=deploy-domains.d.ts.map