@indigoai-us/hq-cli 5.299.0 → 5.301.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 +26 -0
- package/assets/scaffold/core/scripts/token-usage-report.sh +9 -0
- package/dist/command-catalog.generated.d.ts +32 -6
- package/dist/command-catalog.generated.js +38 -6
- package/dist/commands/__fixtures__/access-vault.d.ts +2 -0
- package/dist/commands/__fixtures__/access-vault.js +1 -1
- package/dist/commands/access.d.ts +2 -1
- package/dist/commands/access.js +58 -49
- package/dist/commands/cloud-provision.js +51 -2
- package/dist/commands/cloud.js +12 -7
- package/dist/commands/core-company-index-scope-flag.d.ts +3 -0
- package/dist/commands/core-company-index-scope-flag.js +6 -0
- package/dist/commands/core-job-native-utils.d.ts +6 -0
- package/dist/commands/core-job-native-utils.js +80 -0
- package/dist/commands/core-job-native.d.ts +2 -4
- package/dist/commands/core-job-native.js +6 -10
- package/dist/commands/core-job-notify-native.d.ts +36 -0
- package/dist/commands/core-job-notify-native.js +359 -0
- package/dist/commands/core-job-remediate-native.d.ts +26 -0
- package/dist/commands/core-job-remediate-native.js +374 -0
- package/dist/commands/core.js +26 -8
- package/dist/commands/files.d.ts +1 -0
- package/dist/commands/files.js +90 -14
- package/dist/commands/integrations-api.d.ts +6 -6
- package/dist/commands/integrations-api.js +4 -13
- package/dist/commands/integrations-manage.js +1 -4
- package/dist/commands/lanes-message.js +78 -37
- package/dist/commands/lanes-resume.js +247 -210
- package/dist/commands/lanes-shared.d.ts +5 -1
- package/dist/commands/lanes.d.ts +4 -0
- package/dist/commands/lanes.js +7 -4
- package/dist/commands/meetings.js +35 -16
- package/dist/commands/safe-extract.d.ts +4 -4
- package/dist/commands/safe-extract.js +6 -7
- package/dist/lib/core-utils/token-usage-report.js +17 -3
- package/dist/lib/index-render/companies.d.ts +4 -1
- package/dist/lib/index-render/companies.js +66 -3
- package/dist/lib/index-render/index.d.ts +1 -0
- package/dist/lib/index-render/index.js +2 -1
- package/dist/lib/index-render/shared.d.ts +1 -1
- package/dist/lib/index-render/shared.js +4 -2
- package/dist/lib/lanes/reconcile.js +22 -4
- package/dist/lib/lanes/story-switch.d.ts +21 -0
- package/dist/lib/lanes/story-switch.js +75 -0
- package/dist/lib/lanes/types.d.ts +25 -0
- package/dist/lib/lanes/types.js +1 -1
- package/dist/lib/lanes/watcher.js +15 -4
- package/dist/lib/mesh/live/daemon/mqtt-events.d.ts +7 -0
- package/dist/lib/mesh/live/daemon/mqtt-events.js +2 -0
- package/dist/lib/mesh/live/daemon/mqtt-events.test-d.d.ts +2 -0
- package/dist/lib/mesh/live/daemon/mqtt-events.test-d.js +10 -0
- package/dist/lib/mesh/live/daemon/presence.d.ts +2 -2
- package/dist/lib/mesh/live/daemon/work-subscribe.d.ts +2 -2
- package/dist/utils/self-update.js +51 -4
- package/dist/utils/staged-npm-install.d.ts +16 -0
- package/dist/utils/staged-npm-install.js +264 -0
- package/dist/utils/update-command-supervisor.cjs +53 -1
- package/dist/utils/version-gate.d.ts +8 -0
- package/dist/utils/version-gate.js +82 -15
- package/package.json +2 -2
- package/dist/lib/install-path-compatibility-flag.d.ts +0 -9
- package/dist/lib/install-path-compatibility-flag.js +0 -12
|
@@ -74,33 +74,24 @@ export async function installIntegration(token, companyUid, input) {
|
|
|
74
74
|
}
|
|
75
75
|
return (await res.json());
|
|
76
76
|
}
|
|
77
|
-
export async function uninstallIntegration(token, companyUid,
|
|
77
|
+
export async function uninstallIntegration(token, companyUid, target) {
|
|
78
78
|
const res = await vaultApiFetch({
|
|
79
79
|
token,
|
|
80
80
|
path: "/v1/integrations/factory/uninstall",
|
|
81
81
|
method: "POST",
|
|
82
|
-
body: { companyUid,
|
|
82
|
+
body: { companyUid, ...target },
|
|
83
83
|
});
|
|
84
84
|
if (!res.ok)
|
|
85
85
|
await raiseForResponse(res, "Failed to disconnect the app");
|
|
86
86
|
return (await res.json());
|
|
87
87
|
}
|
|
88
|
-
/**
|
|
89
|
-
* Permanently remove a revoked connection tombstone. The admin purge endpoint
|
|
90
|
-
* deliberately accepts only the connection id: it derives the company and
|
|
91
|
-
* enforces owner authorization from the authenticated connection record.
|
|
92
|
-
*/
|
|
88
|
+
/** Permanently remove a revoked connection tombstone for one company. */
|
|
93
89
|
export async function purgeConnection(token, companyUid, connectionId) {
|
|
94
|
-
// Keep the company in this client's call signature with the other
|
|
95
|
-
// connection mutations. It is resolved before the target connection so a
|
|
96
|
-
// caller cannot use a slug from a different company, but the server's purge
|
|
97
|
-
// contract intentionally takes only connectionId in its body.
|
|
98
|
-
void companyUid;
|
|
99
90
|
const res = await vaultApiFetch({
|
|
100
91
|
token,
|
|
101
92
|
path: "/v1/integrations/admin/purge",
|
|
102
93
|
method: "POST",
|
|
103
|
-
body: { connectionId },
|
|
94
|
+
body: { companyUid, connectionId },
|
|
104
95
|
});
|
|
105
96
|
if (!res.ok)
|
|
106
97
|
await raiseForResponse(res, "Failed to purge the revoked connection");
|
|
@@ -610,9 +610,6 @@ export function registerManageCommands(integrations) {
|
|
|
610
610
|
const companyUid = await getCompanyUid(token, opts.company);
|
|
611
611
|
const connection = await resolveConnection(token, companyUid, app, opts);
|
|
612
612
|
const installationId = connection.installation?.id;
|
|
613
|
-
if (!installationId) {
|
|
614
|
-
throw new IntegrationsCliError(`${connectionLabel(connection)} was not installed through the app catalog, so it cannot be disconnected from here.`, { expected: true });
|
|
615
|
-
}
|
|
616
613
|
if (!opts.yes) {
|
|
617
614
|
const label = connectionLabel(connection);
|
|
618
615
|
// Warning + prompt go to stderr: with --json, stdout must stay parseable,
|
|
@@ -625,7 +622,7 @@ export function registerManageCommands(integrations) {
|
|
|
625
622
|
throw new IntegrationsCliError("Not disconnected. Re-run with --yes if you are sure.", { expected: true });
|
|
626
623
|
}
|
|
627
624
|
}
|
|
628
|
-
const result = await uninstallIntegration(token, companyUid, installationId);
|
|
625
|
+
const result = await uninstallIntegration(token, companyUid, installationId ? { installationId } : { connectionId: connection.id });
|
|
629
626
|
if (opts.json) {
|
|
630
627
|
printJson(result);
|
|
631
628
|
return;
|
|
@@ -8,6 +8,7 @@ import { dispatchLaneDelivery } from "../lib/lanes/delivery-core.js";
|
|
|
8
8
|
import { dropboxInboxHasMessages, drainDropbox, formatDropboxMessages, formatMonitorEvent, requeueDropboxMessages } from "../lib/lanes/dropbox.js";
|
|
9
9
|
import { isPidAlive, runWatcherLoop, WATCHER_OUT_MAX_BYTES, watcherOutLogPath, writeWatcherDecision } from "../lib/lanes/watcher.js";
|
|
10
10
|
import { laneStories, laneStory, storyWarning } from "../lib/lanes/stories.js";
|
|
11
|
+
import { artifactIdentityKeys, rollbackStorySwitchAttribution, storySwitchNotice } from "../lib/lanes/story-switch.js";
|
|
11
12
|
import { laneRunDir, probePidRecord, readPidRecord, readProcStarttime, spawnLaneWorker } from "../lib/lanes/spawn.js";
|
|
12
13
|
import { keepAliveExclusion, keepAliveSupersededBy, LANE_RUNNING_SUPERSEDED_MESSAGE_DELIVERY_FLAG, LANE_SUPERSESSION_LINEAGE_AWARE_FLAG, loadRetiredLaneIds } from "../lib/lanes/keep-alive.js";
|
|
13
14
|
import { readLanesRegistryFlag } from "../lib/lanes/registry-flag.js";
|
|
@@ -212,8 +213,11 @@ export function createLaneMessageHandlers(deps) {
|
|
|
212
213
|
})();
|
|
213
214
|
let accepted = false;
|
|
214
215
|
let claimedMessages = [];
|
|
216
|
+
let storySwitchRollback;
|
|
217
|
+
let storySwitchDeliveryStarted = false;
|
|
215
218
|
const markAccepted = () => {
|
|
216
219
|
accepted = true;
|
|
220
|
+
storySwitchDeliveryStarted = true;
|
|
217
221
|
opts.onAccepted?.();
|
|
218
222
|
};
|
|
219
223
|
let text = opts.text;
|
|
@@ -392,19 +396,21 @@ export function createLaneMessageHandlers(deps) {
|
|
|
392
396
|
if ((opts.project !== undefined || opts.story !== undefined) && ctx.storyLedgerEnabled()) {
|
|
393
397
|
validateProjectStories(hqRoot, projectId, [storyId], lane.company?.slug);
|
|
394
398
|
}
|
|
399
|
+
const notice = storySwitchNotice(lane.project_id, lane.story_id, projectId, storyId);
|
|
400
|
+
const promptedText = notice === undefined ? text : `${notice}\n\n${text}`;
|
|
395
401
|
const framedMonitorEvent = opts.monitorEvent === undefined
|
|
396
402
|
? undefined
|
|
397
403
|
: formatMonitorEvent({
|
|
398
404
|
monitorId: opts.monitorEvent.monitor_id,
|
|
399
405
|
description: opts.monitorEvent.description,
|
|
400
406
|
sequence: opts.monitorEvent.sequence,
|
|
401
|
-
text,
|
|
407
|
+
text: promptedText,
|
|
402
408
|
});
|
|
403
|
-
const deliveryText = framedMonitorEvent ??
|
|
409
|
+
const deliveryText = framedMonitorEvent ?? promptedText;
|
|
404
410
|
const dropboxMessage = {
|
|
405
411
|
at,
|
|
406
412
|
message_id: messageId,
|
|
407
|
-
text,
|
|
413
|
+
text: promptedText,
|
|
408
414
|
project_id: projectId,
|
|
409
415
|
story_id: storyId,
|
|
410
416
|
...(opts.monitorEvent === undefined ? {} : {
|
|
@@ -414,6 +420,52 @@ export function createLaneMessageHandlers(deps) {
|
|
|
414
420
|
sequence: opts.monitorEvent.sequence,
|
|
415
421
|
}),
|
|
416
422
|
};
|
|
423
|
+
if (projectId !== lane.project_id || storyId !== lane.story_id) {
|
|
424
|
+
lane = casUpdateLane(hqRoot, laneId, (current) => {
|
|
425
|
+
const already = current.attribution_history.some((entry) => entry.message_id === messageId);
|
|
426
|
+
if (already)
|
|
427
|
+
return current;
|
|
428
|
+
const existingStory = laneStory(current, projectId, storyId);
|
|
429
|
+
storySwitchRollback = {
|
|
430
|
+
message_id: messageId,
|
|
431
|
+
project_id: current.project_id,
|
|
432
|
+
story_id: current.story_id,
|
|
433
|
+
no_story_reason: current.no_story_reason,
|
|
434
|
+
...(!existingStory ? {
|
|
435
|
+
added_story: { project_id: projectId, story_id: storyId, status: "in_progress", added_at: at, updated_at: at },
|
|
436
|
+
} : {}),
|
|
437
|
+
story_switch_unacknowledged: current.story_switch_unacknowledged,
|
|
438
|
+
};
|
|
439
|
+
return {
|
|
440
|
+
...current,
|
|
441
|
+
project_id: projectId,
|
|
442
|
+
story_id: storyId,
|
|
443
|
+
no_story_reason: storyId ? undefined : current.no_story_reason,
|
|
444
|
+
stories: laneStory(current, projectId, storyId)
|
|
445
|
+
? laneStories(current)
|
|
446
|
+
: [
|
|
447
|
+
...laneStories(current),
|
|
448
|
+
{ project_id: projectId, story_id: storyId, status: "in_progress", added_at: at, updated_at: at },
|
|
449
|
+
],
|
|
450
|
+
attribution_history: appendCappedHistory(current.attribution_history, {
|
|
451
|
+
project_id: projectId,
|
|
452
|
+
story_id: storyId,
|
|
453
|
+
message_id: messageId,
|
|
454
|
+
at,
|
|
455
|
+
}),
|
|
456
|
+
story_switch_pending: {
|
|
457
|
+
previous_project_id: current.project_id,
|
|
458
|
+
previous_story_id: current.story_id,
|
|
459
|
+
project_id: projectId,
|
|
460
|
+
story_id: storyId,
|
|
461
|
+
message_id: messageId,
|
|
462
|
+
at,
|
|
463
|
+
previous_artifact_keys: artifactIdentityKeys(current.last_envelope?.artifacts),
|
|
464
|
+
},
|
|
465
|
+
story_switch_unacknowledged: undefined,
|
|
466
|
+
};
|
|
467
|
+
});
|
|
468
|
+
}
|
|
417
469
|
let resumed = null;
|
|
418
470
|
let move = null;
|
|
419
471
|
let queuedOnAdmission = false;
|
|
@@ -436,6 +488,8 @@ export function createLaneMessageHandlers(deps) {
|
|
|
436
488
|
});
|
|
437
489
|
lane = move.lane;
|
|
438
490
|
if (move.queued) {
|
|
491
|
+
storySwitchDeliveryStarted = true;
|
|
492
|
+
deps.onLaneMessageQueued?.(laneId, "account_move");
|
|
439
493
|
archiveResumeMessage(hqRoot, laneId, dropboxMessage);
|
|
440
494
|
}
|
|
441
495
|
}
|
|
@@ -461,8 +515,11 @@ export function createLaneMessageHandlers(deps) {
|
|
|
461
515
|
accountSelection: selection,
|
|
462
516
|
});
|
|
463
517
|
lane = move.lane;
|
|
464
|
-
if (move.queued)
|
|
518
|
+
if (move.queued) {
|
|
519
|
+
storySwitchDeliveryStarted = true;
|
|
520
|
+
deps.onLaneMessageQueued?.(laneId, "account_move");
|
|
465
521
|
archiveResumeMessage(hqRoot, laneId, dropboxMessage);
|
|
522
|
+
}
|
|
466
523
|
}
|
|
467
524
|
else {
|
|
468
525
|
lane = persistClaudeAccountSelection(hqRoot, lane, selection);
|
|
@@ -491,6 +548,7 @@ export function createLaneMessageHandlers(deps) {
|
|
|
491
548
|
throw new LanesError("lane_not_accepting_messages", operatorMessageRefusalReason(lane.state), { lane_id: laneId, state: lane.state });
|
|
492
549
|
}
|
|
493
550
|
appendDropboxMessage(hqRoot, laneId, dropboxMessage);
|
|
551
|
+
storySwitchDeliveryStarted = true;
|
|
494
552
|
return null;
|
|
495
553
|
},
|
|
496
554
|
resume: async () => {
|
|
@@ -512,7 +570,7 @@ export function createLaneMessageHandlers(deps) {
|
|
|
512
570
|
}
|
|
513
571
|
archiveResumeMessage(hqRoot, laneId, dropboxMessage);
|
|
514
572
|
queuedOnAdmission = true;
|
|
515
|
-
|
|
573
|
+
const queued = casUpdateLane(hqRoot, laneId, (current) => {
|
|
516
574
|
if (current.version !== lane.version || current.state !== lane.state) {
|
|
517
575
|
throw new LanesError("lane_admission_conflict", `Lane ${laneId} changed while message admission was checked`, {
|
|
518
576
|
lane_id: laneId,
|
|
@@ -539,6 +597,9 @@ export function createLaneMessageHandlers(deps) {
|
|
|
539
597
|
},
|
|
540
598
|
};
|
|
541
599
|
});
|
|
600
|
+
storySwitchDeliveryStarted = true;
|
|
601
|
+
deps.onLaneMessageQueued?.(laneId, "admission");
|
|
602
|
+
return queued;
|
|
542
603
|
}
|
|
543
604
|
const started = spawnLaneWorker(hqRoot, lane, {
|
|
544
605
|
env: ctx.env,
|
|
@@ -565,6 +626,8 @@ export function createLaneMessageHandlers(deps) {
|
|
|
565
626
|
compact: opts.compact !== false,
|
|
566
627
|
effort: resumeEffort ?? recordedResumeEffort(lane),
|
|
567
628
|
});
|
|
629
|
+
storySwitchDeliveryStarted = true;
|
|
630
|
+
deps.onLaneWorkerStarted?.(laneId, "message");
|
|
568
631
|
archiveResumeMessage(hqRoot, laneId, dropboxMessage);
|
|
569
632
|
return started;
|
|
570
633
|
}, hireGrantContext);
|
|
@@ -576,41 +639,10 @@ export function createLaneMessageHandlers(deps) {
|
|
|
576
639
|
markAccepted();
|
|
577
640
|
}
|
|
578
641
|
// Every accepted message moves the compaction reference forward.
|
|
579
|
-
|
|
642
|
+
const next = casUpdateLane(hqRoot, laneId, (current) => ({
|
|
580
643
|
...resetKeepAliveProgress(current),
|
|
581
644
|
last_message_at: at,
|
|
582
645
|
}));
|
|
583
|
-
if (projectId !== lane.project_id || storyId !== lane.story_id) {
|
|
584
|
-
next = casUpdateLane(hqRoot, laneId, (current) => {
|
|
585
|
-
const already = current.attribution_history.some((entry) => entry.message_id === messageId);
|
|
586
|
-
if (already)
|
|
587
|
-
return current;
|
|
588
|
-
return {
|
|
589
|
-
...current,
|
|
590
|
-
project_id: projectId,
|
|
591
|
-
story_id: storyId,
|
|
592
|
-
no_story_reason: storyId ? undefined : current.no_story_reason,
|
|
593
|
-
stories: laneStory(current, projectId, storyId)
|
|
594
|
-
? laneStories(current)
|
|
595
|
-
: [
|
|
596
|
-
...laneStories(current),
|
|
597
|
-
{
|
|
598
|
-
project_id: projectId,
|
|
599
|
-
story_id: storyId,
|
|
600
|
-
status: "in_progress",
|
|
601
|
-
added_at: at,
|
|
602
|
-
updated_at: at,
|
|
603
|
-
},
|
|
604
|
-
],
|
|
605
|
-
attribution_history: appendCappedHistory(current.attribution_history, {
|
|
606
|
-
project_id: projectId,
|
|
607
|
-
story_id: storyId,
|
|
608
|
-
message_id: messageId,
|
|
609
|
-
at,
|
|
610
|
-
}),
|
|
611
|
-
};
|
|
612
|
-
});
|
|
613
|
-
}
|
|
614
646
|
// What this command can claim when it returns: the message is durably
|
|
615
647
|
// written (accepted). Delivery to the model is asynchronous in both
|
|
616
648
|
// mechanisms. `dropbox` delivers on the worker's next tool call, and only
|
|
@@ -660,6 +692,15 @@ export function createLaneMessageHandlers(deps) {
|
|
|
660
692
|
});
|
|
661
693
|
}
|
|
662
694
|
catch (err) {
|
|
695
|
+
if (storySwitchRollback !== undefined && !storySwitchDeliveryStarted) {
|
|
696
|
+
try {
|
|
697
|
+
casUpdateLane(hqRoot, laneId, (current) => rollbackStorySwitchAttribution(current, storySwitchRollback));
|
|
698
|
+
}
|
|
699
|
+
catch (rollbackErr) {
|
|
700
|
+
const rollbackMessage = rollbackErr instanceof Error ? rollbackErr.message : String(rollbackErr);
|
|
701
|
+
process.stderr.write(`Could not roll back story attribution after message failure: ${rollbackMessage}\n`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
663
704
|
if (claimedMessages.length > 0 && !accepted) {
|
|
664
705
|
const error = err instanceof Error ? err.message : String(err);
|
|
665
706
|
writeWatcherDecision(watcherOutLogPath(hqRoot, laneId), {
|