@indigoai-us/hq-cli 5.245.0 → 5.247.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 +35 -0
- package/dist/command-catalog.generated.d.ts +5 -2
- package/dist/command-catalog.generated.js +6 -2
- package/dist/commands/agent-kit.js +4 -0
- package/dist/commands/lanes.js +48 -18
- package/dist/lib/agent-kit/creds.d.ts +2 -12
- package/dist/lib/agent-kit/creds.js +1 -60
- package/dist/lib/agent-kit/fallback.js +2 -1
- package/dist/lib/agent-kit/inbox-state.js +2 -2
- package/dist/lib/agent-kit/kit-config.js +2 -2
- package/dist/lib/agent-kit/mcp/attachments.js +4 -16
- package/dist/lib/agent-kit/private-file.d.ts +29 -0
- package/dist/lib/agent-kit/private-file.js +91 -0
- package/dist/lib/agent-kit/run/heartbeat.js +2 -2
- package/dist/lib/agent-kit/run/inbox.js +3 -4
- package/dist/lib/agent-kit/wake.js +5 -4
- 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/lanes/keep-alive.d.ts +5 -2
- package/dist/lib/lanes/keep-alive.js +24 -4
- package/dist/lib/lanes/reconcile.js +14 -7
- package/package.json +2 -2
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { LaneRecord, QuestionRecord } from "./types.js";
|
|
2
2
|
export declare const LEAD_LANE_KEEP_ALIVE_FLAG = "lanes.lead-keep-alive";
|
|
3
3
|
export declare const LEAD_LANE_KEEP_ALIVE_DEFAULT_ENABLED = false;
|
|
4
|
+
/** Missing or unreadable registry values retain the legacy supersession behavior. */
|
|
5
|
+
export declare const LANE_SUPERSESSION_LINEAGE_AWARE_FLAG = "lanes.supersession-lineage-aware";
|
|
6
|
+
export declare const LANE_SUPERSESSION_LINEAGE_AWARE_DEFAULT_ENABLED = false;
|
|
4
7
|
export declare const LEAD_LANE_KEEP_ALIVE_MAX_RESUMES = 24;
|
|
5
8
|
export declare const LEAD_LANE_KEEP_ALIVE_BASE_BACKOFF_MS: number;
|
|
6
9
|
export declare const LEAD_LANE_KEEP_ALIVE_MAX_BACKOFF_MS: number;
|
|
@@ -27,7 +30,7 @@ export declare function retiredLaneRegistryPath(hqRoot: string): string;
|
|
|
27
30
|
export declare function loadRetiredLaneIds(hqRoot: string): ReadonlySet<string>;
|
|
28
31
|
/** IDs may be stored bare or with an owner-host suffix after an underscore. */
|
|
29
32
|
export declare function isRetiredLaneId(laneId: string, retiredLaneIds: ReadonlySet<string>): boolean;
|
|
30
|
-
export declare function keepAliveSupersededBy(lane: LaneRecord, lanes: readonly LaneRecord[]): LaneRecord | undefined;
|
|
31
|
-
export declare function keepAliveExclusion(lane: LaneRecord, lanes: readonly LaneRecord[], retiredLaneIds: ReadonlySet<string
|
|
33
|
+
export declare function keepAliveSupersededBy(lane: LaneRecord, lanes: readonly LaneRecord[], lineageAware?: boolean): LaneRecord | undefined;
|
|
34
|
+
export declare function keepAliveExclusion(lane: LaneRecord, lanes: readonly LaneRecord[], retiredLaneIds: ReadonlySet<string>, lineageAware?: boolean): "retired" | "superseded" | undefined;
|
|
32
35
|
export declare function leadLaneKeepAliveBackoffMs(attempt: number): number;
|
|
33
36
|
//# sourceMappingURL=keep-alive.d.ts.map
|
|
@@ -5,6 +5,9 @@ import { dropboxInboxHasMessages } from "./dropbox.js";
|
|
|
5
5
|
import { listQuestionIds, readQuestion } from "./store.js";
|
|
6
6
|
export const LEAD_LANE_KEEP_ALIVE_FLAG = "lanes.lead-keep-alive";
|
|
7
7
|
export const LEAD_LANE_KEEP_ALIVE_DEFAULT_ENABLED = false;
|
|
8
|
+
/** Missing or unreadable registry values retain the legacy supersession behavior. */
|
|
9
|
+
export const LANE_SUPERSESSION_LINEAGE_AWARE_FLAG = "lanes.supersession-lineage-aware";
|
|
10
|
+
export const LANE_SUPERSESSION_LINEAGE_AWARE_DEFAULT_ENABLED = false;
|
|
8
11
|
export const LEAD_LANE_KEEP_ALIVE_MAX_RESUMES = 24;
|
|
9
12
|
export const LEAD_LANE_KEEP_ALIVE_BASE_BACKOFF_MS = 5 * 60 * 1000;
|
|
10
13
|
export const LEAD_LANE_KEEP_ALIVE_MAX_BACKOFF_MS = 60 * 60 * 1000;
|
|
@@ -119,11 +122,22 @@ export function isRetiredLaneId(laneId, retiredLaneIds) {
|
|
|
119
122
|
}
|
|
120
123
|
return false;
|
|
121
124
|
}
|
|
122
|
-
export function keepAliveSupersededBy(lane, lanes) {
|
|
125
|
+
export function keepAliveSupersededBy(lane, lanes, lineageAware = LANE_SUPERSESSION_LINEAGE_AWARE_DEFAULT_ENABLED) {
|
|
123
126
|
const createdAt = Date.parse(lane.created_at);
|
|
124
127
|
if (!Number.isFinite(createdAt))
|
|
125
128
|
return undefined;
|
|
126
129
|
const lanesById = new Map(lanes.map((candidate) => [candidate.lane_id, candidate]));
|
|
130
|
+
const targetAncestorIds = new Set();
|
|
131
|
+
if (lineageAware) {
|
|
132
|
+
let parentLaneId = lane.senior.kind === "lane" ? lane.senior.id : undefined;
|
|
133
|
+
while (parentLaneId) {
|
|
134
|
+
if (targetAncestorIds.has(parentLaneId))
|
|
135
|
+
break;
|
|
136
|
+
targetAncestorIds.add(parentLaneId);
|
|
137
|
+
const parent = lanesById.get(parentLaneId);
|
|
138
|
+
parentLaneId = parent?.senior.kind === "lane" ? parent.senior.id : undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
127
141
|
return lanes.find((candidate) => {
|
|
128
142
|
if (candidate.lane_id === lane.lane_id || Date.parse(candidate.created_at) <= createdAt)
|
|
129
143
|
return false;
|
|
@@ -132,6 +146,8 @@ export function keepAliveSupersededBy(lane, lanes) {
|
|
|
132
146
|
: candidate.company?.uid === lane.company.uid;
|
|
133
147
|
if (!sameCompany)
|
|
134
148
|
return false;
|
|
149
|
+
if (lineageAware && targetAncestorIds.has(candidate.lane_id))
|
|
150
|
+
return false;
|
|
135
151
|
// Any descendant is part of this lead's work tree, not a replacement lead.
|
|
136
152
|
let parentLaneId = candidate.senior.kind === "lane" ? candidate.senior.id : undefined;
|
|
137
153
|
const visitedLaneIds = new Set();
|
|
@@ -144,18 +160,22 @@ export function keepAliveSupersededBy(lane, lanes) {
|
|
|
144
160
|
const parent = lanesById.get(parentLaneId);
|
|
145
161
|
parentLaneId = parent?.senior.kind === "lane" ? parent.senior.id : undefined;
|
|
146
162
|
}
|
|
163
|
+
const sameLaneSenior = lane.senior.kind === "lane" &&
|
|
164
|
+
candidate.senior.kind === "lane" &&
|
|
165
|
+
candidate.senior.id === lane.senior.id;
|
|
147
166
|
const sameProfile = lane.worker_profile !== undefined &&
|
|
148
|
-
candidate.worker_profile === lane.worker_profile
|
|
167
|
+
candidate.worker_profile === lane.worker_profile &&
|
|
168
|
+
!(lineageAware && sameLaneSenior);
|
|
149
169
|
const projectLead = lane.project_id !== undefined &&
|
|
150
170
|
candidate.project_id === lane.project_id &&
|
|
151
171
|
(candidate.hire_grant ?? 0) > 0;
|
|
152
172
|
return sameProfile || projectLead;
|
|
153
173
|
});
|
|
154
174
|
}
|
|
155
|
-
export function keepAliveExclusion(lane, lanes, retiredLaneIds) {
|
|
175
|
+
export function keepAliveExclusion(lane, lanes, retiredLaneIds, lineageAware = LANE_SUPERSESSION_LINEAGE_AWARE_DEFAULT_ENABLED) {
|
|
156
176
|
if (isRetiredLaneId(lane.lane_id, retiredLaneIds))
|
|
157
177
|
return "retired";
|
|
158
|
-
return keepAliveSupersededBy(lane, lanes) === undefined ? undefined : "superseded";
|
|
178
|
+
return keepAliveSupersededBy(lane, lanes, lineageAware) === undefined ? undefined : "superseded";
|
|
159
179
|
}
|
|
160
180
|
export function leadLaneKeepAliveBackoffMs(attempt) {
|
|
161
181
|
if (!Number.isSafeInteger(attempt) || attempt < 1) {
|
|
@@ -22,7 +22,7 @@ import { ANSWERED_QUESTIONS_FILE, armLaneWatcher, envelopeRepairMode, isPidRecor
|
|
|
22
22
|
import { appendCappedHistory, lanesStoreRoot, parseLaneRecord, parseQuestionRecord, readLane, readQuestion, updateLane, updateQuestion, } from "./store.js";
|
|
23
23
|
import { applyThrottleDecision, decideAdmission, defaultThrottleDeps, emptyThrottleState, evaluateThrottle, isCpuCheckEnabled, readAvailableMemMb, readThrottleState, resolveCpuBusyFraction, throttleStatePath, writeThrottleState, } from "./throttle.js";
|
|
24
24
|
import { readLanesRegistryFlag } from "./registry-flag.js";
|
|
25
|
-
import { LEAD_LANE_KEEP_ALIVE_FLAG, LEAD_LANE_KEEP_ALIVE_INTERRUPTED_RESUME_TEXT, LEAD_LANE_KEEP_ALIVE_MAX_RESUMES, LEAD_LANE_KEEP_ALIVE_RESUME_TEXT, canResumeDoneKeepAliveLane, hasPendingKeepAliveWork, keepAliveExclusion, loadRetiredLaneIds, leadLaneKeepAliveBackoffMs, undeliveredAnsweredQuestions, } from "./keep-alive.js";
|
|
25
|
+
import { LEAD_LANE_KEEP_ALIVE_FLAG, LEAD_LANE_KEEP_ALIVE_INTERRUPTED_RESUME_TEXT, LEAD_LANE_KEEP_ALIVE_MAX_RESUMES, LEAD_LANE_KEEP_ALIVE_RESUME_TEXT, LANE_SUPERSESSION_LINEAGE_AWARE_FLAG, canResumeDoneKeepAliveLane, hasPendingKeepAliveWork, keepAliveExclusion, loadRetiredLaneIds, leadLaneKeepAliveBackoffMs, undeliveredAnsweredQuestions, } from "./keep-alive.js";
|
|
26
26
|
import { providerSupportsSessionResume } from "./delivery.js";
|
|
27
27
|
import { applyDefaultQuotaHold, readQuotaSignal, recordAccountQuota } from "./quota.js";
|
|
28
28
|
import { answeredQuestionEntries, questionRecordRefusalCode, raiseEnvelopeQuestions, resolveQuestionCompanyWithFallback, } from "./questions.js";
|
|
@@ -821,17 +821,24 @@ export async function runPassBody(hqRoot, deps) {
|
|
|
821
821
|
keepAliveFlagCompanies.set(key, lane.company);
|
|
822
822
|
}
|
|
823
823
|
const keepAliveFlagByCompany = new Map();
|
|
824
|
+
const supersessionLineageAwareByCompany = new Map();
|
|
824
825
|
const env = deps.env ?? process.env;
|
|
825
826
|
await Promise.all([...keepAliveFlagCompanies.entries()].map(async ([key, company]) => {
|
|
826
|
-
|
|
827
|
+
const options = {
|
|
827
828
|
company: company ?? undefined,
|
|
828
829
|
env,
|
|
829
|
-
}
|
|
830
|
+
};
|
|
831
|
+
const [keepAliveEnabled, lineageAware] = await Promise.all([
|
|
832
|
+
readRegistryFlag(LEAD_LANE_KEEP_ALIVE_FLAG, options),
|
|
833
|
+
readRegistryFlag(LANE_SUPERSESSION_LINEAGE_AWARE_FLAG, options),
|
|
834
|
+
]);
|
|
835
|
+
keepAliveFlagByCompany.set(key, keepAliveEnabled);
|
|
836
|
+
supersessionLineageAwareByCompany.set(key, lineageAware);
|
|
830
837
|
}));
|
|
831
838
|
await withAllLaneAdmissionLocks(hqRoot, async () => {
|
|
832
839
|
const freshLanes = loadLaneRecords(hqRoot, summary);
|
|
833
840
|
const freshQuestions = loadQuestionRecords(hqRoot, summary);
|
|
834
|
-
resumeKeepAlive(hqRoot, freshLanes, freshQuestions, summary, deps, now, keepAliveFlagByCompany);
|
|
841
|
+
resumeKeepAlive(hqRoot, freshLanes, freshQuestions, summary, deps, now, keepAliveFlagByCompany, supersessionLineageAwareByCompany);
|
|
835
842
|
const drainLanes = loadLaneRecords(hqRoot, summary);
|
|
836
843
|
await admitQueued(hqRoot, drainLanes, summary, deps, now);
|
|
837
844
|
await resumeAwaiting(hqRoot, drainLanes, freshQuestions, summary, deps);
|
|
@@ -1546,7 +1553,7 @@ function latestEnvelopeMtimeMs(hqRoot, lane, ref) {
|
|
|
1546
1553
|
throw new LanesError("keep_alive_envelope_timestamp_unavailable", `Cannot stat latest envelope for lane ${lane.lane_id}: ${err instanceof Error ? err.message : String(err)}`, { lane_id: lane.lane_id, path: filePath });
|
|
1547
1554
|
}
|
|
1548
1555
|
}
|
|
1549
|
-
function resumeKeepAlive(hqRoot, lanes, questions, summary, deps, now, flagByCompany) {
|
|
1556
|
+
function resumeKeepAlive(hqRoot, lanes, questions, summary, deps, now, flagByCompany, supersessionLineageAwareByCompany) {
|
|
1550
1557
|
const nowMs = now.getTime();
|
|
1551
1558
|
const nowIso = now.toISOString();
|
|
1552
1559
|
const config = loadLanesConfig(hqRoot);
|
|
@@ -1702,7 +1709,7 @@ function resumeKeepAlive(hqRoot, lanes, questions, summary, deps, now, flagByCom
|
|
|
1702
1709
|
recordKeepAliveSkip(hqRoot, lane, "retired_list_invalid", summary, deps);
|
|
1703
1710
|
continue;
|
|
1704
1711
|
}
|
|
1705
|
-
const exclusion = keepAliveExclusion(lane, lanes, retiredLaneIds);
|
|
1712
|
+
const exclusion = keepAliveExclusion(lane, lanes, retiredLaneIds, supersessionLineageAwareByCompany.get(keepAliveCompanyKey(lane.company)) === true);
|
|
1706
1713
|
if (exclusion !== undefined) {
|
|
1707
1714
|
recordKeepAliveSkip(hqRoot, lane, exclusion, summary, deps);
|
|
1708
1715
|
continue;
|
|
@@ -1790,7 +1797,7 @@ function resumeKeepAlive(hqRoot, lanes, questions, summary, deps, now, flagByCom
|
|
|
1790
1797
|
continue;
|
|
1791
1798
|
}
|
|
1792
1799
|
const currentLanes = loadLaneRecords(hqRoot, summary);
|
|
1793
|
-
const currentExclusion = keepAliveExclusion(current, currentLanes, retiredLaneIds);
|
|
1800
|
+
const currentExclusion = keepAliveExclusion(current, currentLanes, retiredLaneIds, supersessionLineageAwareByCompany.get(keepAliveCompanyKey(current.company)) === true);
|
|
1794
1801
|
if (currentExclusion !== undefined) {
|
|
1795
1802
|
recordKeepAliveSkip(hqRoot, current, currentExclusion, summary, deps);
|
|
1796
1803
|
continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@indigoai-us/hq-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.247.0",
|
|
4
4
|
"description": "HQ by Indigo management CLI — modules and cloud sync",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@aws-sdk/client-iot-data-plane": "^3.1096.0",
|
|
46
46
|
"@aws-sdk/client-s3": "^3.1049.0",
|
|
47
|
-
"@indigoai-us/hq-cloud": "~6.18.
|
|
47
|
+
"@indigoai-us/hq-cloud": "~6.18.10",
|
|
48
48
|
"@indigoai-us/hq-flags-client": "^0.1.2",
|
|
49
49
|
"@sentry/node": "^10.49.0",
|
|
50
50
|
"@tobilu/qmd": "2.5.3",
|