@indigoai-us/hq-cli 5.327.0 → 5.328.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 +5 -0
- package/assets/scaffold/core/scripts/hq-dm-bind.sh +1 -1
- package/assets/scaffold/core/scripts/hq-job-run.sh +8 -8
- package/assets/scaffold/core/scripts/ontology-audience-grant.sh +1 -1
- package/assets/scaffold/core/scripts/ontology-candidate.sh +1 -1
- package/assets/scaffold/core/scripts/resolve-company.sh +1 -1
- package/dist/commands/mcp-serve.js +1 -1
- package/dist/node-network-compat-fast.js +4 -0
- package/dist/utils/vault-api.js +16 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.328.0] — 2026-10-02
|
|
6
|
+
- Keep successful JSON responses readable if vault API plan-limit inspection cannot reconstruct its buffered response.
|
|
7
|
+
- Fixed bundled scaffold checks that could misclassify matching records when `grep -q` closed a pipe under `pipefail`.
|
|
8
|
+
- Keep `hq mcp serve` initialization lightweight by avoiding the full flag registry and network-family compatibility setup.
|
|
9
|
+
|
|
5
10
|
## [5.327.0] — 2026-10-02
|
|
6
11
|
- Reduce hook-time startup imports for repo-run-registry and isolate hook-helper handlers from sibling modules.
|
|
7
12
|
- Keep package-root Sentry diagnostics off the fast-route import path unless root diagnostics are needed.
|
|
@@ -329,7 +329,7 @@ mention_line() {
|
|
|
329
329
|
cmd_bind() {
|
|
330
330
|
local ch="${1:-}"; [ -n "$ch" ] || die "bind needs a channel name (see: hq channels)"
|
|
331
331
|
ch="${ch#\#}"
|
|
332
|
-
hq channels 2>/dev/null | grep
|
|
332
|
+
hq channels 2>/dev/null | grep -- "hq dm $ch " >/dev/null || die "no channel named '$ch' (see: hq channels)"
|
|
333
333
|
bash "$SESSION_SH" set dm_channel "$ch" >/dev/null
|
|
334
334
|
local sk; sk="$(latest_sk "$ch")"
|
|
335
335
|
printf '%s\n' "$sk" > "$(cursor_file)"
|
|
@@ -323,24 +323,24 @@ classify_failure() {
|
|
|
323
323
|
local lower
|
|
324
324
|
lower="$(printf '%s' "$tail_txt" | tr '[:upper:]' '[:lower:]')"
|
|
325
325
|
|
|
326
|
-
if printf '%s' "$lower" | grep -
|
|
327
|
-
'not logged in|please log in|authentication (failed|required)|unauthorized|401|invalid.*(token|credential)|credentials? (missing|expired|invalid)|device.?code|login required'; then
|
|
326
|
+
if printf '%s' "$lower" | grep -E \
|
|
327
|
+
'not logged in|please log in|authentication (failed|required)|unauthorized|401|invalid.*(token|credential)|credentials? (missing|expired|invalid)|device.?code|login required' >/dev/null; then
|
|
328
328
|
printf 'auth'
|
|
329
329
|
return
|
|
330
330
|
fi
|
|
331
|
-
if printf '%s' "$lower" | grep -
|
|
332
|
-
'secret.*(not found|missing|denied|not visible|not shared)|hq secrets.*(fail|error|denied)|missing vault|access denied.*secret'; then
|
|
331
|
+
if printf '%s' "$lower" | grep -E \
|
|
332
|
+
'secret.*(not found|missing|denied|not visible|not shared)|hq secrets.*(fail|error|denied)|missing vault|access denied.*secret' >/dev/null; then
|
|
333
333
|
printf 'secrets'
|
|
334
334
|
return
|
|
335
335
|
fi
|
|
336
336
|
# Avoid matching job metadata like timeout_seconds=N in the log header.
|
|
337
|
-
if printf '%s' "$lower" | grep -
|
|
338
|
-
'(^|[^_])timed out|command timed out|deadline exceeded|killed by timeout|exit[=:][[:space:]]*124\b'; then
|
|
337
|
+
if printf '%s' "$lower" | grep -E \
|
|
338
|
+
'(^|[^_])timed out|command timed out|deadline exceeded|killed by timeout|exit[=:][[:space:]]*124\b' >/dev/null; then
|
|
339
339
|
printf 'timeout'
|
|
340
340
|
return
|
|
341
341
|
fi
|
|
342
|
-
if printf '%s' "$lower" | grep -
|
|
343
|
-
'connection (refused|reset|timed out)|network is unreachable|temporary failure|econnreset|enotfound|no space left|i/o error|transport error|dns (fail|error)|http[/ ]*(502|503|504)|statusingesterror|api unreachable'; then
|
|
342
|
+
if printf '%s' "$lower" | grep -E \
|
|
343
|
+
'connection (refused|reset|timed out)|network is unreachable|temporary failure|econnreset|enotfound|no space left|i/o error|transport error|dns (fail|error)|http[/ ]*(502|503|504)|statusingesterror|api unreachable' >/dev/null; then
|
|
344
344
|
printf 'infra'
|
|
345
345
|
return
|
|
346
346
|
fi
|
|
@@ -67,7 +67,7 @@ for aud in "$C"/signals/@*/_audience.yaml; do
|
|
|
67
67
|
# attendees), so they are already company identities; emails must be members.
|
|
68
68
|
case "$who" in
|
|
69
69
|
prs_*|agt_*) ;;
|
|
70
|
-
*) if !
|
|
70
|
+
*) if ! grep -qxF "$who" <<<"$members"; then echo "skip $who (not a member of $co)" >&2; skipped=$((skipped+1)); continue; fi ;;
|
|
71
71
|
esac
|
|
72
72
|
for p in $prefixes; do grant "$p" "$who"; done
|
|
73
73
|
done
|
|
@@ -79,7 +79,7 @@ id="$(printf '%s\n%s\n%s\n%s' "$kind" "$type" "$key" "$norm_body" | sha)"
|
|
|
79
79
|
|
|
80
80
|
dir="$root/companies/$co/$store/_candidates/$(date -u +%Y-%m-%d)"
|
|
81
81
|
# Idempotent across days: the same candidate already written (pending or done) is a no-op.
|
|
82
|
-
if find "$root/companies/$co/$store/_candidates" -name "$id.md" 2>/dev/null
|
|
82
|
+
if [ -n "$(find "$root/companies/$co/$store/_candidates" -name "$id.md" -print -quit 2>/dev/null)" ]; then
|
|
83
83
|
echo "exists $id"; exit 0
|
|
84
84
|
fi
|
|
85
85
|
mkdir -p "$dir"
|
|
@@ -15,7 +15,7 @@ import * as fs from "node:fs";
|
|
|
15
15
|
import * as os from "node:os";
|
|
16
16
|
import * as path from "node:path";
|
|
17
17
|
import { CLI_VERSION } from "../cli-version.js";
|
|
18
|
-
import { HQ_ANYWHERE_RUNTIME_FLAG } from "
|
|
18
|
+
import { HQ_ANYWHERE_RUNTIME_FLAG } from "../lib/anywhere-runtime-flag-key.js";
|
|
19
19
|
import { anywhereRuntimeEnabledFromSnapshot } from "../lib/anywhere-runtime-fast-flag.js";
|
|
20
20
|
import { createLineSplitter, HqdClientError, hqdRequest, hqdSocketPath } from "../lib/daemon/protocol.js";
|
|
21
21
|
export const MCP_PROTOCOL_VERSIONS = ["2025-06-18", "2025-03-26", "2024-11-05"];
|
|
@@ -11,6 +11,10 @@ export function shouldConfigureNodeNetworkCompatibility(argv) {
|
|
|
11
11
|
const fastCore = parseFastCore(argv);
|
|
12
12
|
if (fastCore)
|
|
13
13
|
return fastCore.entry.requiresNodeNetworkCompatibility === true;
|
|
14
|
+
// The MCP shim only forwards over the local hqd socket; it does not make
|
|
15
|
+
// outbound network requests and does not need the network-family patch.
|
|
16
|
+
if (argv.length === 4 && argv[2] === "mcp" && argv[3] === "serve")
|
|
17
|
+
return false;
|
|
14
18
|
// The lightweight secrets route still makes vault API requests.
|
|
15
19
|
if (parseSecretsEnvFastRequest(argv))
|
|
16
20
|
return true;
|
package/dist/utils/vault-api.js
CHANGED
|
@@ -111,14 +111,20 @@ function identityLookupTimeoutMs() {
|
|
|
111
111
|
* exits on Linux CI. Reading once + re-wrapping fully drains the stream.
|
|
112
112
|
*/
|
|
113
113
|
async function peekPlanLimitStatus(response, options = {}) {
|
|
114
|
+
let bufferedBody;
|
|
114
115
|
try {
|
|
115
116
|
if (!response.ok)
|
|
116
117
|
return response;
|
|
118
|
+
// Fetch forbids bodies on these statuses. Leave the original response
|
|
119
|
+
// untouched instead of consuming it and trying to reconstruct it later.
|
|
120
|
+
if ([101, 103, 204, 205, 304].includes(response.status))
|
|
121
|
+
return response;
|
|
117
122
|
const ct = response.headers.get('content-type') ?? '';
|
|
118
123
|
if (!ct.includes('application/json') && !ct.includes('+json')) {
|
|
119
124
|
return response;
|
|
120
125
|
}
|
|
121
126
|
const buf = await response.arrayBuffer();
|
|
127
|
+
bufferedBody = buf;
|
|
122
128
|
try {
|
|
123
129
|
const text = new TextDecoder().decode(buf);
|
|
124
130
|
try {
|
|
@@ -141,7 +147,16 @@ async function peekPlanLimitStatus(response, options = {}) {
|
|
|
141
147
|
}
|
|
142
148
|
catch (err) {
|
|
143
149
|
// Only secret-load callers need the body-read error for offline fallback.
|
|
144
|
-
// Other endpoints retain the
|
|
150
|
+
// Other endpoints retain the best-effort peek behavior only while the
|
|
151
|
+
// original body is still readable.
|
|
152
|
+
if (bufferedBody !== undefined) {
|
|
153
|
+
// Retry with safe metadata: statusText can itself make Response
|
|
154
|
+
// construction throw after the original stream has already been drained.
|
|
155
|
+
return new Response(bufferedBody, {
|
|
156
|
+
status: response.status,
|
|
157
|
+
headers: response.headers,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
145
160
|
if (options.throwOnBodyReadError)
|
|
146
161
|
throw err;
|
|
147
162
|
return response;
|