@indigoai-us/hq-cli 5.275.0 → 5.276.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 +36 -0
- package/README.md +12 -0
- package/assets/bot-workers/setup/context/USER-GUIDE.md +4 -4
- package/dist/commands/core-checkpoint.d.ts +4 -2
- package/dist/commands/core-checkpoint.js +34 -3
- package/dist/commands/core-command-catalog.d.ts +4 -2
- package/dist/commands/core-command-catalog.js +5 -2
- package/dist/commands/core-ontology.js +3 -3
- package/dist/commands/core.js +1 -1
- package/dist/commands/daemon.d.ts +1 -0
- package/dist/commands/daemon.js +2 -1
- package/dist/commands/feedback.d.ts +6 -0
- package/dist/commands/feedback.js +86 -37
- package/dist/commands/lanes.js +3 -2
- package/dist/commands/run-feature-telemetry.d.ts +3 -0
- package/dist/commands/run-feature-telemetry.js +6 -0
- package/dist/commands/run.js +3 -2
- package/dist/commands/secrets.js +7 -1
- package/dist/commands/whoami.d.ts +4 -6
- package/dist/commands/whoami.js +39 -8
- package/dist/fast-core.d.ts +6 -7
- package/dist/fast-core.js +22 -8
- package/dist/fast-scaffold.d.ts +16 -7
- package/dist/fast-scaffold.js +13 -8
- package/dist/index.js +16 -1
- package/dist/lib/billing/plan-lock.d.ts +3 -1
- package/dist/lib/billing/plan-lock.js +7 -1
- package/dist/lib/checkpoint-ontology/company.d.ts +8 -4
- package/dist/lib/checkpoint-ontology/company.js +15 -7
- package/dist/lib/checkpoint-ontology/plan.d.ts +23 -0
- package/dist/lib/checkpoint-ontology/plan.js +53 -4
- package/dist/lib/checkpoint-ontology/queued-touches.d.ts +32 -0
- package/dist/lib/checkpoint-ontology/queued-touches.js +193 -0
- package/dist/lib/core-utils/timeout-guard-native.d.ts +7 -0
- package/dist/lib/core-utils/timeout-guard-native.js +40 -0
- package/dist/lib/core-utils/timeout-guard.d.ts +3 -3
- package/dist/lib/core-utils/timeout-guard.js +28 -13
- package/dist/lib/flag-registry.d.ts +12 -7
- package/dist/lib/flag-registry.js +66 -75
- package/dist/lib/flag-snapshot-file.d.ts +20 -0
- package/dist/lib/flag-snapshot-file.js +91 -0
- package/dist/lib/lanes/reconcile.js +20 -4
- package/dist/lib/process-flag-company-context.d.ts +8 -0
- package/dist/lib/process-flag-company-context.js +67 -0
- package/dist/main.js +3 -1
- package/dist/native-fast-route.d.ts +3 -0
- package/dist/native-fast-route.js +39 -0
- package/dist/utils/cli-telemetry.d.ts +26 -2
- package/dist/utils/cli-telemetry.js +178 -3
- package/dist/utils/hq-root-resolver.d.ts +13 -0
- package/dist/utils/hq-root-resolver.js +103 -0
- package/dist/utils/scaffold-fast-import-guard.js +6 -1
- package/dist/utils/vault-api.d.ts +8 -0
- package/dist/utils/vault-api.js +13 -1
- package/package.json +1 -1
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** Lightweight HQ-root resolver shared by cloud commands and fast flag scope. */
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import * as yaml from "js-yaml";
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the HQ tree root using the same precedence as the Cognito helpers:
|
|
8
|
+
* explicit HQ_ROOT, nearest cwd root, installer records, known locations, then
|
|
9
|
+
* the historical ~/hq fallback (or an error when requested).
|
|
10
|
+
*/
|
|
11
|
+
export function resolveDefaultHqRoot(opts = {}) {
|
|
12
|
+
const env = opts.env ?? process.env;
|
|
13
|
+
const home = opts.home ?? os.homedir();
|
|
14
|
+
if (env.HQ_ROOT)
|
|
15
|
+
return path.resolve(env.HQ_ROOT);
|
|
16
|
+
let cur = path.resolve(opts.cwd ?? process.cwd());
|
|
17
|
+
while (cur !== path.dirname(cur)) {
|
|
18
|
+
if (isHqRoot(cur))
|
|
19
|
+
return cur;
|
|
20
|
+
cur = path.dirname(cur);
|
|
21
|
+
}
|
|
22
|
+
const fromConfig = readHqRootFromHqConfig(path.join(home, ".hq"));
|
|
23
|
+
if (fromConfig)
|
|
24
|
+
return path.resolve(fromConfig);
|
|
25
|
+
const discovered = discoverHqRootViaCoreYaml(home);
|
|
26
|
+
if (discovered)
|
|
27
|
+
return discovered;
|
|
28
|
+
if (opts.onMissing === "throw") {
|
|
29
|
+
throw new Error("Could not find HQ root. Run this command from within your HQ directory " +
|
|
30
|
+
"(must contain core.yaml AND a companies/ subdirectory), set $HQ_ROOT, " +
|
|
31
|
+
"or install HQ via the installer/menubar so ~/.hq/menubar.json records " +
|
|
32
|
+
"its location.");
|
|
33
|
+
}
|
|
34
|
+
return path.join(home, "hq");
|
|
35
|
+
}
|
|
36
|
+
function readHqRootFromHqConfig(hqConfigDir) {
|
|
37
|
+
const fromMenubar = readJsonStringField(path.join(hqConfigDir, "menubar.json"), "hqPath");
|
|
38
|
+
if (fromMenubar)
|
|
39
|
+
return fromMenubar;
|
|
40
|
+
return readJsonStringField(path.join(hqConfigDir, "config.json"), "hqFolderPath");
|
|
41
|
+
}
|
|
42
|
+
function readJsonStringField(file, field) {
|
|
43
|
+
try {
|
|
44
|
+
const parsed = JSON.parse(fs.readFileSync(file, "utf-8"));
|
|
45
|
+
const value = parsed[field];
|
|
46
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function hqDiscoveryCandidates(home) {
|
|
53
|
+
return [
|
|
54
|
+
path.join(home, "HQ"),
|
|
55
|
+
path.join(home, "hq"),
|
|
56
|
+
path.join(home, "Documents", "HQ"),
|
|
57
|
+
path.join(home, "Documents", "hq"),
|
|
58
|
+
path.join(home, "Desktop", "HQ"),
|
|
59
|
+
path.join(home, "Desktop", "hq"),
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
function discoverHqRootViaCoreYaml(home) {
|
|
63
|
+
return hqDiscoveryCandidates(home).find(isValidHqRootSignature);
|
|
64
|
+
}
|
|
65
|
+
function isValidHqRootSignature(dir) {
|
|
66
|
+
const canonical = path.join(dir, "core", "core.yaml");
|
|
67
|
+
const legacy = path.join(dir, "core.yaml");
|
|
68
|
+
let file;
|
|
69
|
+
if (fileExists(canonical))
|
|
70
|
+
file = canonical;
|
|
71
|
+
else if (fileExists(legacy))
|
|
72
|
+
file = legacy;
|
|
73
|
+
else
|
|
74
|
+
return false;
|
|
75
|
+
try {
|
|
76
|
+
const parsed = yaml.load(fs.readFileSync(file, "utf-8"));
|
|
77
|
+
return !!parsed && typeof parsed === "object" && "version" in parsed && "hqVersion" in parsed;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function fileExists(file) {
|
|
84
|
+
try {
|
|
85
|
+
return fs.statSync(file).isFile();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function isHqRoot(dir) {
|
|
92
|
+
const hasCoreYaml = fileExists(path.join(dir, "core", "core.yaml")) ||
|
|
93
|
+
fileExists(path.join(dir, "core.yaml"));
|
|
94
|
+
if (!hasCoreYaml)
|
|
95
|
+
return false;
|
|
96
|
+
try {
|
|
97
|
+
return fs.statSync(path.join(dir, "companies")).isDirectory();
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=hq-root-resolver.js.map
|
|
@@ -4,6 +4,8 @@ export function forbiddenFastPathModules(loadedModules, distDirectory) {
|
|
|
4
4
|
const dist = path.resolve(distDirectory);
|
|
5
5
|
const main = path.join(dist, "main.js");
|
|
6
6
|
const commands = `${path.join(dist, "commands")}${path.sep}`;
|
|
7
|
+
const flagRegistry = path.join(dist, "lib", "flag-registry.js");
|
|
8
|
+
const coreCommand = path.join(dist, "commands", "core.js");
|
|
7
9
|
return [...new Set(loadedModules.map((loaded) => {
|
|
8
10
|
if (loaded.startsWith("file:")) {
|
|
9
11
|
try {
|
|
@@ -16,7 +18,10 @@ export function forbiddenFastPathModules(loadedModules, distDirectory) {
|
|
|
16
18
|
return path.resolve(loaded);
|
|
17
19
|
}))]
|
|
18
20
|
.filter((loaded) => path.resolve(loaded) === main ||
|
|
19
|
-
path.resolve(loaded).startsWith(commands)
|
|
21
|
+
path.resolve(loaded).startsWith(commands) ||
|
|
22
|
+
path.resolve(loaded) === flagRegistry ||
|
|
23
|
+
path.resolve(loaded) === coreCommand ||
|
|
24
|
+
path.resolve(loaded).includes(`${path.sep}node_modules${path.sep}@sentry${path.sep}node${path.sep}`))
|
|
20
25
|
.sort();
|
|
21
26
|
}
|
|
22
27
|
export function assertFastPathStaysCommandGraphFree(loadedModules, distDirectory) {
|
|
@@ -47,6 +47,13 @@ export declare function rewritePathForApiKey(path: string): string | null;
|
|
|
47
47
|
* authorization or request signing depends on it.
|
|
48
48
|
*/
|
|
49
49
|
export declare const HQ_CLIENT_NAME = "@indigoai-us/hq-cli";
|
|
50
|
+
type VaultApiRequestTargetOptions = Pick<VaultApiOptions, "baseUrl" | "token" | "path" | "query">;
|
|
51
|
+
/**
|
|
52
|
+
* Run vaultApiFetch's synchronous, client-side request checks without sending
|
|
53
|
+
* the request. Commands with prior uploads use this to fail before creating
|
|
54
|
+
* objects that a later local refusal would leave orphaned.
|
|
55
|
+
*/
|
|
56
|
+
export declare function assertVaultApiRequestSupported(opts: VaultApiRequestTargetOptions): void;
|
|
50
57
|
export declare function vaultApiFetch(opts: VaultApiOptions): Promise<Response>;
|
|
51
58
|
/**
|
|
52
59
|
* Public (NONE-auth) GET against the vault API — no bearer token. The
|
|
@@ -77,4 +84,5 @@ export declare function getEntityUid(token: string, opts: {
|
|
|
77
84
|
}, options?: {
|
|
78
85
|
allowOfflineScopeFallback?: boolean;
|
|
79
86
|
}): Promise<string>;
|
|
87
|
+
export {};
|
|
80
88
|
//# sourceMappingURL=vault-api.d.ts.map
|
package/dist/utils/vault-api.js
CHANGED
|
@@ -155,7 +155,7 @@ export function rewritePathForApiKey(path) {
|
|
|
155
155
|
* authorization or request signing depends on it.
|
|
156
156
|
*/
|
|
157
157
|
export const HQ_CLIENT_NAME = "@indigoai-us/hq-cli";
|
|
158
|
-
|
|
158
|
+
function resolveVaultApiRequestTarget(opts) {
|
|
159
159
|
let path = opts.path;
|
|
160
160
|
if (opts.token.startsWith("hqk_")) {
|
|
161
161
|
const rewritten = rewritePathForApiKey(path);
|
|
@@ -172,6 +172,18 @@ export async function vaultApiFetch(opts) {
|
|
|
172
172
|
url.searchParams.set(k, v);
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
|
+
return { path, url };
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Run vaultApiFetch's synchronous, client-side request checks without sending
|
|
179
|
+
* the request. Commands with prior uploads use this to fail before creating
|
|
180
|
+
* objects that a later local refusal would leave orphaned.
|
|
181
|
+
*/
|
|
182
|
+
export function assertVaultApiRequestSupported(opts) {
|
|
183
|
+
resolveVaultApiRequestTarget(opts);
|
|
184
|
+
}
|
|
185
|
+
export async function vaultApiFetch(opts) {
|
|
186
|
+
const { path, url } = resolveVaultApiRequestTarget(opts);
|
|
175
187
|
const method = opts.method ?? 'GET';
|
|
176
188
|
const safeUrl = url.search ? `${url.origin}${url.pathname}?<redacted>` : `${url.origin}${url.pathname}`;
|
|
177
189
|
Sentry.addBreadcrumb({
|