@indigoai-us/hq-cli 5.345.142 → 5.345.144

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 (61) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/dist/command-catalog.generated.d.ts +278 -6
  3. package/dist/command-catalog.generated.js +341 -6
  4. package/dist/command-registration-plan.d.ts +6 -0
  5. package/dist/command-registration-plan.js +1 -0
  6. package/dist/commands/agent-enroll.d.ts +1 -0
  7. package/dist/commands/agent-enroll.js +7 -0
  8. package/dist/commands/agents.d.ts +25 -3
  9. package/dist/commands/agents.js +57 -4
  10. package/dist/commands/api-keys.js +66 -8
  11. package/dist/commands/billing-sponsor.d.ts +4 -0
  12. package/dist/commands/billing-sponsor.js +48 -5
  13. package/dist/commands/billing-usage.d.ts +59 -0
  14. package/dist/commands/billing-usage.js +162 -0
  15. package/dist/commands/billing.d.ts +9 -0
  16. package/dist/commands/billing.js +29 -2
  17. package/dist/commands/core-policy.js +76 -13
  18. package/dist/commands/library-add.d.ts +120 -0
  19. package/dist/commands/library-add.js +434 -0
  20. package/dist/commands/library-caption.d.ts +112 -0
  21. package/dist/commands/library-caption.js +393 -0
  22. package/dist/commands/library-link.d.ts +32 -0
  23. package/dist/commands/library-link.js +95 -0
  24. package/dist/commands/library.d.ts +72 -0
  25. package/dist/commands/library.js +527 -0
  26. package/dist/commands/meetings.d.ts +8 -0
  27. package/dist/commands/meetings.js +25 -2
  28. package/dist/commands/storage-offload.d.ts +16 -2
  29. package/dist/commands/storage-offload.js +55 -4
  30. package/dist/commands/storage.d.ts +8 -1
  31. package/dist/commands/storage.js +6 -2
  32. package/dist/hq-cloud-sync-runner/bin/sync-runner.js +2410 -2063
  33. package/dist/hq-cloud-sync-runner/package.json +1 -1
  34. package/dist/lib/billing/plan-lock.d.ts +15 -1
  35. package/dist/lib/billing/plan-lock.js +45 -5
  36. package/dist/lib/billing/usage-card.d.ts +82 -0
  37. package/dist/lib/billing/usage-card.js +198 -0
  38. package/dist/lib/billing/usage-cost.d.ts +214 -0
  39. package/dist/lib/billing/usage-cost.js +440 -0
  40. package/dist/lib/billing/usage-only.d.ts +87 -0
  41. package/dist/lib/billing/usage-only.js +262 -0
  42. package/dist/lib/billing/usage-rate-card.d.ts +51 -0
  43. package/dist/lib/billing/usage-rate-card.js +62 -0
  44. package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
  45. package/dist/lib/flag-registry-worker-source.generated.js +1 -1
  46. package/dist/lib/plan-limit-nag.d.ts +4 -6
  47. package/dist/lib/plan-limit-nag.js +19 -1
  48. package/dist/lib/provider-launcher.d.ts +22 -0
  49. package/dist/lib/provider-launcher.js +65 -0
  50. package/dist/lib/search-index/index.d.ts +2 -0
  51. package/dist/lib/search-index/index.js +34 -0
  52. package/dist/lib/search-index/max-doc-bytes.d.ts +2 -1
  53. package/dist/lib/search-index/max-doc-bytes.js +2 -1
  54. package/dist/main.d.ts +9 -0
  55. package/dist/main.js +20 -3
  56. package/dist/utils/billing-gate.d.ts +19 -4
  57. package/dist/utils/billing-gate.js +25 -4
  58. package/dist/utils/plan-gate-error.d.ts +10 -0
  59. package/dist/utils/plan-gate-error.js +54 -0
  60. package/dist/utils/vault-api.js +4 -1
  61. package/package.json +2 -2
@@ -119,7 +119,16 @@ export function resolveMinBytes(flag, env) {
119
119
  return parseSize(fromEnv);
120
120
  return DEFAULT_MIN_BYTES;
121
121
  }
122
- export function renderPointer(p) {
122
+ /** Company-vault key for library bytes: content-addressed by sha256, relative to the company bucket. */
123
+ export function companyOffloadKey(sha256) {
124
+ return `${OFFLOAD_PREFIX}${sha256}`;
125
+ }
126
+ /**
127
+ * Render a placeholder. `assetBlock` is the fenced `hq-asset` metadata block
128
+ * (from hq-cloud's `formatCloudAssetBlock`) that `hq library add` appends after
129
+ * the footer so the placeholder is a searchable library asset.
130
+ */
131
+ export function renderPointer(p, assetBlock) {
123
132
  const lines = [POINTER_HEADER, `path: ${p.path}`, `size: ${p.size}`, `sha256: ${p.sha256 ?? "unknown"}`];
124
133
  if (p.gitBlob)
125
134
  lines.push(`git-blob: ${p.gitBlob}`);
@@ -131,6 +140,8 @@ export function renderPointer(p) {
131
140
  if (p.orphaned)
132
141
  lines.push("orphaned: true");
133
142
  lines.push(`retrieve: hq storage fetch "${p.path}"`, POINTER_FOOTER, "");
143
+ if (assetBlock)
144
+ lines.push(assetBlock.endsWith("\n") ? assetBlock : `${assetBlock}\n`);
134
145
  return lines.join("\n");
135
146
  }
136
147
  /** ETags compare without the surrounding quotes S3 returns. */
@@ -142,9 +153,11 @@ const HEX64 = /^[0-9a-f]{64}$/;
142
153
  /**
143
154
  * Parse pointer text. Returns null for anything that is not a valid v1 pointer.
144
155
  *
145
- * Two shapes are valid:
156
+ * Three shapes are valid:
146
157
  * - an offload copy: `vault: personal`, key = offloadKey(git-blob), with a
147
158
  * git blob id to verify against;
159
+ * - a library copy: `vault: company`, key = companyOffloadKey(sha256), with
160
+ * the sha256 to verify against (written by `hq library add`);
148
161
  * - a vault object recorded by sync: either vault, a non-offload key, and a
149
162
  * `remote-etag` to verify against (sha256 may be `unknown`).
150
163
  */
@@ -191,10 +204,22 @@ export function parsePointer(text) {
191
204
  const isOffloadCopy = p.gitBlob !== undefined && p.key === offloadKey(p.gitBlob);
192
205
  if (isOffloadCopy)
193
206
  return p.vault === "personal" ? p : null;
207
+ if (isCompanyOffloadCopy(p))
208
+ return p;
194
209
  if (p.key.startsWith(OFFLOAD_PREFIX) || !p.remoteEtag)
195
210
  return null;
196
211
  return p;
197
212
  }
213
+ /**
214
+ * Library copy in a company vault: content-addressed under
215
+ * `.hq-offload/blobs/<sha256>`, verified by that sha256 (no git blob, no ETag).
216
+ */
217
+ export function isCompanyOffloadCopy(p) {
218
+ return (p.vault === "company" &&
219
+ p.sha256 !== null &&
220
+ p.gitBlob === undefined &&
221
+ p.key === companyOffloadKey(p.sha256));
222
+ }
198
223
  /** sha256 and git blob id (sha1 of "blob <size>\0" + bytes) in one pass. */
199
224
  export async function digestFile(file) {
200
225
  const size = (await fs.promises.stat(file)).size;
@@ -1320,7 +1345,7 @@ async function downloadVerified(download, key, dest, expect) {
1320
1345
  /** Company slug for a company-vault placeholder, checked against its key. */
1321
1346
  export function companyForPointer(pointer) {
1322
1347
  const m = /^companies\/([^/]+)\/(.+)$/.exec(pointer.path);
1323
- if (!m || m[2] !== pointer.key) {
1348
+ if (!m || (!isCompanyOffloadCopy(pointer) && m[2] !== pointer.key)) {
1324
1349
  throw new Error(`Placeholder for '${pointer.path}' names company vault key '${pointer.key}', which does not match its location. Nothing was changed.`);
1325
1350
  }
1326
1351
  return m[1];
@@ -1377,7 +1402,10 @@ async function fetchPlaceholder(arg, deps, opts) {
1377
1402
  throw new Error(`'${pointer.path}' already exists locally. Move it aside first.`);
1378
1403
  }
1379
1404
  let digest;
1380
- if (pointer.remoteEtag === undefined) {
1405
+ if (isCompanyOffloadCopy(pointer)) {
1406
+ digest = await fetchCompanyOffload(pointer, target, deps);
1407
+ }
1408
+ else if (pointer.remoteEtag === undefined) {
1381
1409
  // Offload copy in the personal vault, verified by git blob id and sha256.
1382
1410
  const store = await deps.openPersonal();
1383
1411
  digest = await downloadVerified((partial) => store.download(pointer.key, partial), pointer.key, target, {
@@ -1392,6 +1420,29 @@ async function fetchPlaceholder(arg, deps, opts) {
1392
1420
  await fs.promises.rm(placeholder, { force: true });
1393
1421
  return { path: pointer.path, bytes: digest.size, sha256: digest.sha256 };
1394
1422
  }
1423
+ /**
1424
+ * Library copy (`hq library add`): download `.hq-offload/blobs/<sha256>` from
1425
+ * the company vault and verify the bytes against that sha256. The object is
1426
+ * content-addressed, so the current ETag is pinned only to keep one download
1427
+ * consistent. Opened only for a company the caller is an active member of.
1428
+ */
1429
+ async function fetchCompanyOffload(pointer, target, deps) {
1430
+ if (!deps.openVaultObjects)
1431
+ throw new Error("This HQ build cannot fetch files from a company library.");
1432
+ const slug = companyForPointer(pointer);
1433
+ const active = deps.activeCompanySlugs ? await deps.activeCompanySlugs() : [];
1434
+ if (!active.includes(slug)) {
1435
+ throw new Error(`You are not an active member of '${slug}', so HQ cannot download this file for you.`);
1436
+ }
1437
+ const store = await deps.openVaultObjects({ vault: "company", slug });
1438
+ const head = await store.head(pointer.key);
1439
+ if (!head)
1440
+ throw new Error(`This file is no longer in the cloud (${pointer.key}).`);
1441
+ return downloadVerified((partial) => store.download(pointer.key, partial, head.etag), pointer.key, target, {
1442
+ sha256: pointer.sha256,
1443
+ size: pointer.size,
1444
+ });
1445
+ }
1395
1446
  /**
1396
1447
  * Placeholder that sync rewrote to a vault object: download pinned to the
1397
1448
  * recorded ETag and verify size (and sha256 when known). A company vault is
@@ -36,7 +36,7 @@
36
36
  import { Command } from "commander";
37
37
  import { type ReclaimReport } from "./storage-core.js";
38
38
  import { S3Client, ListObjectVersionsCommand, DeleteObjectsCommand, type ListObjectVersionsCommandOutput, type DeleteObjectsCommandOutput } from "@aws-sdk/client-s3";
39
- import { type OffloadResult, type OffloadStatus } from "./storage-offload.js";
39
+ import { type OffloadDeps, type OffloadResult, type OffloadStatus } from "./storage-offload.js";
40
40
  export type TrancheId = "7d" | "30d" | "90d" | "365d" | "older";
41
41
  export declare const TRANCHES: readonly {
42
42
  id: TrancheId;
@@ -265,6 +265,11 @@ export declare const NEEDS_YES = "No terminal to confirm in. Re-run with --yes t
265
265
  export declare function confirmOnTty(message: string, input?: NodeJS.ReadableStream & {
266
266
  isTTY?: boolean;
267
267
  }, output?: NodeJS.WritableStream): Promise<boolean>;
268
+ /**
269
+ * Deps for offload/fetch. The only store is the caller's personal vault,
270
+ * resolved from their canonical person entity and vended with `/sts/vend-self`.
271
+ */
272
+ export declare function buildOffloadDeps(): Promise<OffloadDeps>;
268
273
  /**
269
274
  * An S3 client for one vault whose credentials are re-vended before they
270
275
  * expire, plus `revend`, which vends now and returns a client on the new
@@ -296,5 +301,7 @@ export declare function refreshingVendedCredentials(vend: () => Promise<VendedCr
296
301
  sessionToken: string;
297
302
  expiration?: Date;
298
303
  }>;
304
+ /** Production deps. Exported for `hq billing usage`, which reads cloud status only. */
305
+ export declare function buildStorageDeps(): Promise<StorageDeps>;
299
306
  export declare function registerStorageCommand(program: Command): Command;
300
307
  //# sourceMappingURL=storage.d.ts.map
@@ -1003,7 +1003,7 @@ async function signedInVault() {
1003
1003
  * Deps for offload/fetch. The only store is the caller's personal vault,
1004
1004
  * resolved from their canonical person entity and vended with `/sts/vend-self`.
1005
1005
  */
1006
- async function buildOffloadDeps() {
1006
+ export async function buildOffloadDeps() {
1007
1007
  const hqRoot = findHqRoot();
1008
1008
  const personalVault = async () => {
1009
1009
  const { vault } = await signedInVault();
@@ -1189,6 +1189,10 @@ export function refreshingVendedCredentials(vend, now = Date.now, marginMs = 5 *
1189
1189
  return pending;
1190
1190
  };
1191
1191
  }
1192
+ /** Production deps. Exported for `hq billing usage`, which reads cloud status only. */
1193
+ export async function buildStorageDeps() {
1194
+ return buildDeps();
1195
+ }
1192
1196
  async function buildDeps() {
1193
1197
  // Sign-in is lazy so `status` can still report local sections when signed out,
1194
1198
  // and it is resolved again for every cloud call (never once at the start): the
@@ -1323,7 +1327,7 @@ export function registerStorageCommand(program) {
1323
1327
  paths: Array.isArray(opts.current) ? opts.current : undefined,
1324
1328
  dryRun: Boolean(opts.dryRun),
1325
1329
  yes: Boolean(opts.yes),
1326
- }, await buildOffloadDeps());
1330
+ }, { ...(await buildOffloadDeps()), log: (line) => (opts.json ? console.error(line) : console.log(line)) });
1327
1331
  if (!result)
1328
1332
  return;
1329
1333
  console.log(opts.json ? JSON.stringify(result, null, 2) : formatOffload(result));