@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.
- package/CHANGELOG.md +74 -0
- package/dist/command-catalog.generated.d.ts +278 -6
- package/dist/command-catalog.generated.js +341 -6
- package/dist/command-registration-plan.d.ts +6 -0
- package/dist/command-registration-plan.js +1 -0
- package/dist/commands/agent-enroll.d.ts +1 -0
- package/dist/commands/agent-enroll.js +7 -0
- package/dist/commands/agents.d.ts +25 -3
- package/dist/commands/agents.js +57 -4
- package/dist/commands/api-keys.js +66 -8
- package/dist/commands/billing-sponsor.d.ts +4 -0
- package/dist/commands/billing-sponsor.js +48 -5
- package/dist/commands/billing-usage.d.ts +59 -0
- package/dist/commands/billing-usage.js +162 -0
- package/dist/commands/billing.d.ts +9 -0
- package/dist/commands/billing.js +29 -2
- package/dist/commands/core-policy.js +76 -13
- package/dist/commands/library-add.d.ts +120 -0
- package/dist/commands/library-add.js +434 -0
- package/dist/commands/library-caption.d.ts +112 -0
- package/dist/commands/library-caption.js +393 -0
- package/dist/commands/library-link.d.ts +32 -0
- package/dist/commands/library-link.js +95 -0
- package/dist/commands/library.d.ts +72 -0
- package/dist/commands/library.js +527 -0
- package/dist/commands/meetings.d.ts +8 -0
- package/dist/commands/meetings.js +25 -2
- package/dist/commands/storage-offload.d.ts +16 -2
- package/dist/commands/storage-offload.js +55 -4
- package/dist/commands/storage.d.ts +8 -1
- package/dist/commands/storage.js +6 -2
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +2410 -2063
- package/dist/hq-cloud-sync-runner/package.json +1 -1
- package/dist/lib/billing/plan-lock.d.ts +15 -1
- package/dist/lib/billing/plan-lock.js +45 -5
- package/dist/lib/billing/usage-card.d.ts +82 -0
- package/dist/lib/billing/usage-card.js +198 -0
- package/dist/lib/billing/usage-cost.d.ts +214 -0
- package/dist/lib/billing/usage-cost.js +440 -0
- package/dist/lib/billing/usage-only.d.ts +87 -0
- package/dist/lib/billing/usage-only.js +262 -0
- package/dist/lib/billing/usage-rate-card.d.ts +51 -0
- package/dist/lib/billing/usage-rate-card.js +62 -0
- package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
- package/dist/lib/flag-registry-worker-source.generated.js +1 -1
- package/dist/lib/plan-limit-nag.d.ts +4 -6
- package/dist/lib/plan-limit-nag.js +19 -1
- package/dist/lib/provider-launcher.d.ts +22 -0
- package/dist/lib/provider-launcher.js +65 -0
- package/dist/lib/search-index/index.d.ts +2 -0
- package/dist/lib/search-index/index.js +34 -0
- package/dist/lib/search-index/max-doc-bytes.d.ts +2 -1
- package/dist/lib/search-index/max-doc-bytes.js +2 -1
- package/dist/main.d.ts +9 -0
- package/dist/main.js +20 -3
- package/dist/utils/billing-gate.d.ts +19 -4
- package/dist/utils/billing-gate.js +25 -4
- package/dist/utils/plan-gate-error.d.ts +10 -0
- package/dist/utils/plan-gate-error.js +54 -0
- package/dist/utils/vault-api.js +4 -1
- 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
|
-
|
|
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
|
-
*
|
|
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
|
|
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
|
package/dist/commands/storage.js
CHANGED
|
@@ -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));
|