@indigoai-us/hq-cli 5.59.0 → 5.61.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/dist/commands/meetings.js +127 -14
- package/dist/commands/pack-install.d.ts +7 -1
- package/dist/commands/pack-install.js +86 -15
- package/dist/commands/packs.d.ts +2 -1
- package/dist/commands/packs.js +13 -8
- package/dist/commands/secrets.d.ts +5 -0
- package/dist/commands/secrets.js +134 -6
- package/dist/index.d.ts +5 -3
- package/dist/index.js +14 -240
- package/dist/main.d.ts +7 -0
- package/dist/main.js +247 -0
- package/dist/utils/sandbox-runner-client.d.ts +13 -0
- package/dist/utils/sandbox-runner-client.js +82 -5
- package/dist/utils/version-check.d.ts +6 -0
- package/dist/utils/version-check.js +78 -2
- package/package.json +1 -1
- package/src/commands/meetings.test.ts +116 -2
- package/src/commands/meetings.ts +206 -37
- package/src/commands/pack-install.ts +115 -18
- package/src/commands/pack-update-cache.test.ts +149 -0
- package/src/commands/packs.ts +28 -7
- package/src/commands/secrets.test.ts +407 -0
- package/src/commands/secrets.ts +203 -5
- package/src/index.test.ts +32 -0
- package/src/index.ts +11 -274
- package/src/main.ts +283 -0
- package/src/utils/sandbox-runner-client.test.ts +128 -0
- package/src/utils/sandbox-runner-client.ts +99 -3
- package/src/utils/version-check.test.ts +30 -0
- package/src/utils/version-check.ts +72 -0
|
@@ -8,7 +8,9 @@ import { CLI_VERSION } from "../cli-version.js";
|
|
|
8
8
|
const PACKAGE_NAME = "@indigoai-us/hq-cli";
|
|
9
9
|
const REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`;
|
|
10
10
|
const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
11
|
+
const CACHE_TTL_JITTER_MS = 60 * 60 * 1000;
|
|
11
12
|
const FETCH_TIMEOUT_MS = 3_000;
|
|
13
|
+
const REFRESH_LOCK_STALE_MS = 10 * 60 * 1000;
|
|
12
14
|
|
|
13
15
|
interface CacheEntry {
|
|
14
16
|
latest: string;
|
|
@@ -19,6 +21,10 @@ function cachePath(): string {
|
|
|
19
21
|
return path.join(os.homedir(), ".hq", "version-check.json");
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
function lockPath(): string {
|
|
25
|
+
return path.join(os.homedir(), ".hq", "version-check.lock");
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
function isOptedOut(): boolean {
|
|
23
29
|
return process.env.HQ_NO_UPDATE_CHECK === "1";
|
|
24
30
|
}
|
|
@@ -49,6 +55,58 @@ function writeCache(entry: CacheEntry): void {
|
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
|
|
58
|
+
function freshEnough(entry: CacheEntry, now = Date.now()): boolean {
|
|
59
|
+
const jitter = Math.floor(Math.random() * CACHE_TTL_JITTER_MS);
|
|
60
|
+
return now - entry.fetchedAt <= CACHE_TTL_MS - jitter;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function isKnownNoninteractiveStatusProbe(argv: readonly string[] = process.argv): boolean {
|
|
64
|
+
const args = argv.slice(2);
|
|
65
|
+
const positional = args.filter((arg) => !arg.startsWith("-"));
|
|
66
|
+
const json = args.includes("--json") || !process.stdout.isTTY;
|
|
67
|
+
if (!json) return false;
|
|
68
|
+
if (positional[0] === "mcp" && positional[1] === "status") return true;
|
|
69
|
+
if (positional[0] === "packs" && (positional[1] === "list" || positional[1] === "ls")) return true;
|
|
70
|
+
if (
|
|
71
|
+
positional[0] === "packages" &&
|
|
72
|
+
positional[1] === "packs" &&
|
|
73
|
+
(positional[2] === "list" || positional[2] === "ls")
|
|
74
|
+
) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
if ((positional[0] === "sources" || positional[0] === "signals") && positional[1] === "list") {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function acquireRefreshLock(now = Date.now()): (() => void) | null {
|
|
84
|
+
const dir = lockPath();
|
|
85
|
+
try {
|
|
86
|
+
fs.mkdirSync(path.dirname(dir), { recursive: true });
|
|
87
|
+
fs.mkdirSync(dir);
|
|
88
|
+
fs.writeFileSync(path.join(dir, "owner"), `${process.pid}\n${now}\n`);
|
|
89
|
+
return () => {
|
|
90
|
+
try {
|
|
91
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
92
|
+
} catch {
|
|
93
|
+
// best-effort lock cleanup
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
} catch {
|
|
97
|
+
try {
|
|
98
|
+
const stat = fs.statSync(dir);
|
|
99
|
+
if (now - stat.mtimeMs > REFRESH_LOCK_STALE_MS) {
|
|
100
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
101
|
+
return acquireRefreshLock(now);
|
|
102
|
+
}
|
|
103
|
+
} catch {
|
|
104
|
+
// ignore lock inspection failures
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
52
110
|
export function maybeWarnNewVersion(): void {
|
|
53
111
|
if (isOptedOut()) return;
|
|
54
112
|
const entry = readCache();
|
|
@@ -68,7 +126,14 @@ export function maybeWarnNewVersion(): void {
|
|
|
68
126
|
|
|
69
127
|
export async function refreshVersionCache(): Promise<void> {
|
|
70
128
|
if (isOptedOut()) return;
|
|
129
|
+
if (isKnownNoninteractiveStatusProbe()) return;
|
|
130
|
+
const existing = readCache();
|
|
131
|
+
if (existing && freshEnough(existing)) return;
|
|
132
|
+
const releaseLock = acquireRefreshLock();
|
|
133
|
+
if (!releaseLock) return;
|
|
71
134
|
try {
|
|
135
|
+
const lockedExisting = readCache();
|
|
136
|
+
if (lockedExisting && freshEnough(lockedExisting)) return;
|
|
72
137
|
const res = await fetch(REGISTRY_URL, {
|
|
73
138
|
headers: { Accept: "application/json" },
|
|
74
139
|
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
@@ -79,5 +144,12 @@ export async function refreshVersionCache(): Promise<void> {
|
|
|
79
144
|
writeCache({ latest: body.version, fetchedAt: Date.now() });
|
|
80
145
|
} catch {
|
|
81
146
|
// best-effort; offline / registry down / timeout — silent
|
|
147
|
+
} finally {
|
|
148
|
+
releaseLock();
|
|
82
149
|
}
|
|
83
150
|
}
|
|
151
|
+
|
|
152
|
+
export const __test__ = {
|
|
153
|
+
CACHE_TTL_MS,
|
|
154
|
+
isKnownNoninteractiveStatusProbe,
|
|
155
|
+
};
|