@indigoai-us/hq-cli 5.342.18 → 5.343.1
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 +15 -0
- package/dist/command-catalog.generated.d.ts +12 -4
- package/dist/command-catalog.generated.js +14 -4
- package/dist/commands/company.d.ts +12 -0
- package/dist/commands/company.js +103 -6
- package/dist/commands/daemon.js +2 -11
- package/dist/commands/dm.js +10 -1
- package/dist/commands/lanes-shared.d.ts +1 -0
- package/dist/commands/lanes.d.ts +1 -0
- package/dist/commands/lanes.js +11 -0
- package/dist/commands/mesh.js +6 -2
- package/dist/commands/pack-install.d.ts +2 -0
- package/dist/commands/pack-install.js +7 -0
- package/dist/commands/pkg-update.d.ts +2 -0
- package/dist/commands/pkg-update.js +5 -1
- package/dist/commands/secrets.js +2 -3
- package/dist/lib/agent-kit/mcp/tools.js +1 -1
- package/dist/lib/bot/api.d.ts +1 -0
- package/dist/lib/bot/api.js +2 -0
- package/dist/lib/bot/progress.d.ts +12 -14
- package/dist/lib/bot/progress.js +29 -40
- package/dist/lib/bot/run.js +24 -24
- package/dist/lib/core-utils/sentry-report.d.ts +1 -1
- package/dist/lib/core-utils/sentry-report.js +18 -1
- package/dist/lib/daemon/command-call.d.ts +9 -0
- package/dist/lib/daemon/command-call.js +18 -0
- package/dist/lib/doctor/checks/work-context.js +5 -0
- package/dist/lib/lanes/outpost-dispatch.d.ts +1 -0
- package/dist/lib/lanes/outpost-dispatch.js +1 -0
- package/dist/lib/mesh/client.js +11 -0
- package/dist/lib/mesh/denial-codes.d.ts +13 -2
- package/dist/lib/mesh/denial-codes.js +25 -1
- package/dist/lib/mesh/live/daemon/doctor.js +4 -0
- package/dist/lib/work-context/outbox.js +8 -2
- package/dist/utils/cli-telemetry.js +5 -1
- package/dist/utils/install-tree-torn.d.ts +16 -13
- package/dist/utils/install-tree-torn.js +58 -26
- package/dist/utils/resident-package-preload.d.ts +1 -1
- package/dist/utils/resident-package-preload.js +62 -0
- package/dist/utils/secrets-sandbox-resident.d.ts +5 -0
- package/dist/utils/secrets-sandbox-resident.js +8 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.343.1] — 2026-10-04
|
|
6
|
+
|
|
7
|
+
- Include the bounded hq-cli version in `cli_feature_used` telemetry so feature-use rows can be grouped by release.
|
|
8
|
+
|
|
9
|
+
- Release the HQ CLI package-use lease before hq daemon call waits for its daemon response, after preloading the request protocol.
|
|
10
|
+
- Release the package-use lease after Outpost lane message and resume requests are submitted and their result-wait imports are preloaded.
|
|
11
|
+
- Preserve human, agent, and both audience tags when CLI tools and local bots post or reply in channels.
|
|
12
|
+
- Wait for a live installer to finish before retrying a failed CLI import when the install tree is still in flight.
|
|
13
|
+
- Preserve bounded master-hook slow-phase and per-phase timeout attribution in Sentry reports.
|
|
14
|
+
|
|
15
|
+
## [5.343.0] — 2026-10-04
|
|
16
|
+
- `hq company --company <slug> settings set --work-registry-enabled <true|false>` and `--work-mesh-live-enabled <true|false>` let a company owner turn work tracking on or off. Work tracking needs both switches; after either is set the command says whether work tracking is on and prints the exact command for the switch that is still off. `hq company --company <slug> settings get` now also shows both switches for an owner or admin.
|
|
17
|
+
- `hq mesh context requeue` now also re-sends, by default, sessions that were refused while work tracking was off. `hq doctor` and `hq mesh daemon doctor` explain those refusals in plain words.
|
|
18
|
+
- Release the hq-cli package-use lease before the secrets sandbox poll and bounded package downloads after preloading their lazy runtime imports.
|
|
19
|
+
|
|
5
20
|
## [5.342.18] — 2026-10-04
|
|
6
21
|
- Preserve confirmed remote lane-message responses for in-process monitor delivery.
|
|
7
22
|
- Use native TypeScript renderers for `hq core rebuild-index` commands.
|
|
@@ -3204,7 +3204,7 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
3204
3204
|
readonly hidden: false;
|
|
3205
3205
|
}, {
|
|
3206
3206
|
readonly flags: "--audience <human|agent|both>";
|
|
3207
|
-
readonly description: "Tag who this message is for: human (a person must read it), agent (progress/status, hidden from humans by default), or both
|
|
3207
|
+
readonly description: "Tag who this message is for: human (a person must read it), agent (progress/status, hidden from humans by default), or both";
|
|
3208
3208
|
readonly hidden: false;
|
|
3209
3209
|
}];
|
|
3210
3210
|
readonly subcommands: readonly [];
|
|
@@ -5334,7 +5334,7 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
5334
5334
|
readonly options: readonly [];
|
|
5335
5335
|
readonly subcommands: readonly [{
|
|
5336
5336
|
readonly name: "set";
|
|
5337
|
-
readonly description: "Set per-company settings (PUT /company-settings). Require at least one of --crm-enabled / --ontology-enabled / --accounting-enabled / --checkpoint-gate-enabled.";
|
|
5337
|
+
readonly description: "Set per-company settings (PUT /company-settings). Require at least one of --crm-enabled / --ontology-enabled / --accounting-enabled / --checkpoint-gate-enabled / --work-registry-enabled / --work-mesh-live-enabled.";
|
|
5338
5338
|
readonly aliases: readonly [];
|
|
5339
5339
|
readonly hidden: false;
|
|
5340
5340
|
readonly helpOption: true;
|
|
@@ -5358,11 +5358,19 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
5358
5358
|
readonly flags: "--checkpoint-gate-enabled <true|false>";
|
|
5359
5359
|
readonly description: "Require (true) or stop requiring (false) a checkpoint before HQ sessions in this company end a turn";
|
|
5360
5360
|
readonly hidden: false;
|
|
5361
|
+
}, {
|
|
5362
|
+
readonly flags: "--work-registry-enabled <true|false>";
|
|
5363
|
+
readonly description: "Turn work-session registration on or off for this company (default off). Work tracking needs this and --work-mesh-live-enabled";
|
|
5364
|
+
readonly hidden: false;
|
|
5365
|
+
}, {
|
|
5366
|
+
readonly flags: "--work-mesh-live-enabled <true|false>";
|
|
5367
|
+
readonly description: "Turn live work tracking on or off for this company (default off). Work tracking needs this and --work-registry-enabled";
|
|
5368
|
+
readonly hidden: false;
|
|
5361
5369
|
}];
|
|
5362
5370
|
readonly subcommands: readonly [];
|
|
5363
5371
|
}, {
|
|
5364
5372
|
readonly name: "get";
|
|
5365
|
-
readonly description: "Show whether the checkpoint Stop gate is on for this company (GET /company-settings/checkpoint-gate; any member may read it).";
|
|
5373
|
+
readonly description: "Show whether the checkpoint Stop gate is on for this company (GET /company-settings/checkpoint-gate; any member may read it) and, for an owner or admin, the two work tracking switches (GET /company-settings).";
|
|
5366
5374
|
readonly aliases: readonly [];
|
|
5367
5375
|
readonly hidden: false;
|
|
5368
5376
|
readonly helpOption: true;
|
|
@@ -9635,7 +9643,7 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
9635
9643
|
readonly subcommands: readonly [];
|
|
9636
9644
|
}, {
|
|
9637
9645
|
readonly name: "requeue";
|
|
9638
|
-
readonly description: "Requeue quarantined outbox operations (default:
|
|
9646
|
+
readonly description: "Requeue quarantined outbox operations (default: AUTH_DENIED - work-mesh-live gap 10 recovery - plus sessions refused while work tracking was off). Run once after the company owner turns work tracking on";
|
|
9639
9647
|
readonly aliases: readonly [];
|
|
9640
9648
|
readonly hidden: false;
|
|
9641
9649
|
readonly helpOption: true;
|
|
@@ -3874,7 +3874,7 @@ export const COMMAND_CATALOG = [
|
|
|
3874
3874
|
},
|
|
3875
3875
|
{
|
|
3876
3876
|
"flags": "--audience <human|agent|both>",
|
|
3877
|
-
"description": "Tag who this message is for: human (a person must read it), agent (progress/status, hidden from humans by default), or both
|
|
3877
|
+
"description": "Tag who this message is for: human (a person must read it), agent (progress/status, hidden from humans by default), or both",
|
|
3878
3878
|
"hidden": false
|
|
3879
3879
|
}
|
|
3880
3880
|
],
|
|
@@ -6478,7 +6478,7 @@ export const COMMAND_CATALOG = [
|
|
|
6478
6478
|
"subcommands": [
|
|
6479
6479
|
{
|
|
6480
6480
|
"name": "set",
|
|
6481
|
-
"description": "Set per-company settings (PUT /company-settings). Require at least one of --crm-enabled / --ontology-enabled / --accounting-enabled / --checkpoint-gate-enabled.",
|
|
6481
|
+
"description": "Set per-company settings (PUT /company-settings). Require at least one of --crm-enabled / --ontology-enabled / --accounting-enabled / --checkpoint-gate-enabled / --work-registry-enabled / --work-mesh-live-enabled.",
|
|
6482
6482
|
"aliases": [],
|
|
6483
6483
|
"hidden": false,
|
|
6484
6484
|
"helpOption": true,
|
|
@@ -6506,13 +6506,23 @@ export const COMMAND_CATALOG = [
|
|
|
6506
6506
|
"flags": "--checkpoint-gate-enabled <true|false>",
|
|
6507
6507
|
"description": "Require (true) or stop requiring (false) a checkpoint before HQ sessions in this company end a turn",
|
|
6508
6508
|
"hidden": false
|
|
6509
|
+
},
|
|
6510
|
+
{
|
|
6511
|
+
"flags": "--work-registry-enabled <true|false>",
|
|
6512
|
+
"description": "Turn work-session registration on or off for this company (default off). Work tracking needs this and --work-mesh-live-enabled",
|
|
6513
|
+
"hidden": false
|
|
6514
|
+
},
|
|
6515
|
+
{
|
|
6516
|
+
"flags": "--work-mesh-live-enabled <true|false>",
|
|
6517
|
+
"description": "Turn live work tracking on or off for this company (default off). Work tracking needs this and --work-registry-enabled",
|
|
6518
|
+
"hidden": false
|
|
6509
6519
|
}
|
|
6510
6520
|
],
|
|
6511
6521
|
"subcommands": []
|
|
6512
6522
|
},
|
|
6513
6523
|
{
|
|
6514
6524
|
"name": "get",
|
|
6515
|
-
"description": "Show whether the checkpoint Stop gate is on for this company (GET /company-settings/checkpoint-gate; any member may read it).",
|
|
6525
|
+
"description": "Show whether the checkpoint Stop gate is on for this company (GET /company-settings/checkpoint-gate; any member may read it) and, for an owner or admin, the two work tracking switches (GET /company-settings).",
|
|
6516
6526
|
"aliases": [],
|
|
6517
6527
|
"hidden": false,
|
|
6518
6528
|
"helpOption": true,
|
|
@@ -11686,7 +11696,7 @@ export const COMMAND_CATALOG = [
|
|
|
11686
11696
|
},
|
|
11687
11697
|
{
|
|
11688
11698
|
"name": "requeue",
|
|
11689
|
-
"description": "Requeue quarantined outbox operations (default:
|
|
11699
|
+
"description": "Requeue quarantined outbox operations (default: AUTH_DENIED - work-mesh-live gap 10 recovery - plus sessions refused while work tracking was off). Run once after the company owner turns work tracking on",
|
|
11690
11700
|
"aliases": [],
|
|
11691
11701
|
"hidden": false,
|
|
11692
11702
|
"helpOption": true,
|
|
@@ -1,3 +1,15 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* The two per-company switches that together turn work tracking on. The server
|
|
4
|
+
* refuses work-session registration unless both are true. `null` means the
|
|
5
|
+
* values could not be read.
|
|
6
|
+
*/
|
|
7
|
+
interface WorkTrackingSettings {
|
|
8
|
+
workRegistryEnabled: boolean;
|
|
9
|
+
workMeshLiveEnabled: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Plain next steps after a work tracking switch was set, from the effective settings. */
|
|
12
|
+
export declare function workTrackingNextSteps(companySlug: string, settings: WorkTrackingSettings | null): string[];
|
|
2
13
|
export declare function registerCompanyCommand(program: Command): void;
|
|
14
|
+
export {};
|
|
3
15
|
//# sourceMappingURL=company.d.ts.map
|
package/dist/commands/company.js
CHANGED
|
@@ -4,6 +4,64 @@ import { vaultApiFetch, getEntityUid } from "../utils/vault-api.js";
|
|
|
4
4
|
import { registerCompanyTransferCommand } from "./company-transfer.js";
|
|
5
5
|
import { registerCompanyRenameCommand } from "./company-rename.js";
|
|
6
6
|
import { describeRefreshOutcome, refreshCheckpointGateSetting, } from "./core-checkpoint-gate-setting.js";
|
|
7
|
+
/** Both switches from a settings response body, or null unless both are booleans. */
|
|
8
|
+
function workTrackingFromBody(body) {
|
|
9
|
+
const { workRegistryEnabled, workMeshLiveEnabled } = body;
|
|
10
|
+
return typeof workRegistryEnabled === "boolean" && typeof workMeshLiveEnabled === "boolean"
|
|
11
|
+
? { workRegistryEnabled, workMeshLiveEnabled }
|
|
12
|
+
: null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Read both switches from GET /company-settings (owner or admin only). The
|
|
16
|
+
* server returns effective values, so an absent field means the default (off).
|
|
17
|
+
* A refused or failed read returns null rather than a guess.
|
|
18
|
+
*/
|
|
19
|
+
async function readWorkTrackingSettings(token, companyUid) {
|
|
20
|
+
try {
|
|
21
|
+
const res = await vaultApiFetch({
|
|
22
|
+
token,
|
|
23
|
+
path: "/company-settings",
|
|
24
|
+
query: { companyUid },
|
|
25
|
+
});
|
|
26
|
+
if (!res.ok)
|
|
27
|
+
return null;
|
|
28
|
+
const body = (await res.json().catch(() => ({})));
|
|
29
|
+
return {
|
|
30
|
+
workRegistryEnabled: body.workRegistryEnabled === true,
|
|
31
|
+
workMeshLiveEnabled: body.workMeshLiveEnabled === true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Plain next steps after a work tracking switch was set, from the effective settings. */
|
|
39
|
+
export function workTrackingNextSteps(companySlug, settings) {
|
|
40
|
+
const command = `hq company --company ${companySlug} settings`;
|
|
41
|
+
if (!settings) {
|
|
42
|
+
return [`Could not read the settings back. Check both switches with: ${command} get`];
|
|
43
|
+
}
|
|
44
|
+
if (settings.workRegistryEnabled && settings.workMeshLiveEnabled) {
|
|
45
|
+
return [
|
|
46
|
+
"Work tracking is on.",
|
|
47
|
+
"Sessions refused while it was off are held on each machine. " +
|
|
48
|
+
"Each person should run once: hq mesh context requeue",
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
if (settings.workRegistryEnabled) {
|
|
52
|
+
return [
|
|
53
|
+
"Work tracking is not on yet. Sessions will still be refused until live tracking is also on. " +
|
|
54
|
+
`Run: ${command} set --work-mesh-live-enabled true`,
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
if (settings.workMeshLiveEnabled) {
|
|
58
|
+
return [
|
|
59
|
+
"Work tracking is not on yet. Sessions will still be refused until the work registry is also on. " +
|
|
60
|
+
`Run: ${command} set --work-registry-enabled true`,
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
return [`Work tracking is off for ${companySlug}.`];
|
|
64
|
+
}
|
|
7
65
|
/**
|
|
8
66
|
* Parse a `--flag <true|false>` string into a boolean, or throw. Commander
|
|
9
67
|
* passes the raw string; we validate strictly so a typo never silently writes
|
|
@@ -32,11 +90,14 @@ export function registerCompanyCommand(program) {
|
|
|
32
90
|
.command("set")
|
|
33
91
|
.description("Set per-company settings (PUT /company-settings). Require at least one " +
|
|
34
92
|
"of --crm-enabled / --ontology-enabled / --accounting-enabled / " +
|
|
35
|
-
"--checkpoint-gate-enabled
|
|
93
|
+
"--checkpoint-gate-enabled / --work-registry-enabled / " +
|
|
94
|
+
"--work-mesh-live-enabled.")
|
|
36
95
|
.option("--crm-enabled <true|false>", "Enable/disable the native CRM for this company")
|
|
37
96
|
.option("--ontology-enabled <true|false>", "Enable/disable the ontology gardener for this company")
|
|
38
97
|
.option("--accounting-enabled <true|false>", "Enable/disable the accounting pack for this company")
|
|
39
98
|
.option("--checkpoint-gate-enabled <true|false>", "Require (true) or stop requiring (false) a checkpoint before HQ sessions in this company end a turn")
|
|
99
|
+
.option("--work-registry-enabled <true|false>", "Turn work-session registration on or off for this company (default off). Work tracking needs this and --work-mesh-live-enabled")
|
|
100
|
+
.option("--work-mesh-live-enabled <true|false>", "Turn live work tracking on or off for this company (default off). Work tracking needs this and --work-registry-enabled")
|
|
40
101
|
.action(async (opts) => {
|
|
41
102
|
try {
|
|
42
103
|
const companySlug = company.opts().company;
|
|
@@ -47,8 +108,10 @@ export function registerCompanyCommand(program) {
|
|
|
47
108
|
if (opts.crmEnabled === undefined &&
|
|
48
109
|
opts.ontologyEnabled === undefined &&
|
|
49
110
|
opts.accountingEnabled === undefined &&
|
|
50
|
-
opts.checkpointGateEnabled === undefined
|
|
51
|
-
|
|
111
|
+
opts.checkpointGateEnabled === undefined &&
|
|
112
|
+
opts.workRegistryEnabled === undefined &&
|
|
113
|
+
opts.workMeshLiveEnabled === undefined) {
|
|
114
|
+
console.error(chalk.red("Error: provide at least one of --crm-enabled / --ontology-enabled / --accounting-enabled / --checkpoint-gate-enabled / --work-registry-enabled / --work-mesh-live-enabled."));
|
|
52
115
|
process.exit(1);
|
|
53
116
|
}
|
|
54
117
|
const body = {};
|
|
@@ -64,6 +127,14 @@ export function registerCompanyCommand(program) {
|
|
|
64
127
|
if (opts.checkpointGateEnabled !== undefined) {
|
|
65
128
|
body.checkpointGateEnabled = parseBoolFlag(opts.checkpointGateEnabled, "--checkpoint-gate-enabled");
|
|
66
129
|
}
|
|
130
|
+
if (opts.workRegistryEnabled !== undefined) {
|
|
131
|
+
body.workRegistryEnabled = parseBoolFlag(opts.workRegistryEnabled, "--work-registry-enabled");
|
|
132
|
+
}
|
|
133
|
+
if (opts.workMeshLiveEnabled !== undefined) {
|
|
134
|
+
body.workMeshLiveEnabled = parseBoolFlag(opts.workMeshLiveEnabled, "--work-mesh-live-enabled");
|
|
135
|
+
}
|
|
136
|
+
const setsWorkTracking = body.workRegistryEnabled !== undefined ||
|
|
137
|
+
body.workMeshLiveEnabled !== undefined;
|
|
67
138
|
const token = await ensureCognitoToken();
|
|
68
139
|
const companyUid = await getEntityUid(token, { companySlug });
|
|
69
140
|
body.companyUid = companyUid;
|
|
@@ -76,7 +147,9 @@ export function registerCompanyCommand(program) {
|
|
|
76
147
|
if (!res.ok) {
|
|
77
148
|
const errBody = (await res.json().catch(() => ({})));
|
|
78
149
|
if (res.status === 403) {
|
|
79
|
-
console.error(chalk.red(
|
|
150
|
+
console.error(chalk.red(setsWorkTracking
|
|
151
|
+
? "Only the company owner can change this setting."
|
|
152
|
+
: "Requires owner role on this company to change its settings."));
|
|
80
153
|
process.exit(1);
|
|
81
154
|
}
|
|
82
155
|
console.error(chalk.red(`Failed to update company settings: ${errBody.error ?? res.statusText}`));
|
|
@@ -98,6 +171,16 @@ export function registerCompanyCommand(program) {
|
|
|
98
171
|
// The setting is saved; the cache refreshes on the next Stop.
|
|
99
172
|
}
|
|
100
173
|
}
|
|
174
|
+
if (setsWorkTracking) {
|
|
175
|
+
// Registration needs both switches, so report the effective pair:
|
|
176
|
+
// from the PUT response when it echoes both, otherwise from a GET.
|
|
177
|
+
const resBody = (await res.json().catch(() => ({})));
|
|
178
|
+
const effective = workTrackingFromBody(resBody) ??
|
|
179
|
+
(await readWorkTrackingSettings(token, companyUid));
|
|
180
|
+
for (const line of workTrackingNextSteps(companySlug, effective)) {
|
|
181
|
+
console.log(line);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
101
184
|
}
|
|
102
185
|
catch (err) {
|
|
103
186
|
console.error(chalk.red("Error:"), err instanceof Error ? err.message : String(err));
|
|
@@ -107,7 +190,8 @@ export function registerCompanyCommand(program) {
|
|
|
107
190
|
settings
|
|
108
191
|
.command("get")
|
|
109
192
|
.description("Show whether the checkpoint Stop gate is on for this company " +
|
|
110
|
-
"(GET /company-settings/checkpoint-gate; any member may read it)
|
|
193
|
+
"(GET /company-settings/checkpoint-gate; any member may read it) and, " +
|
|
194
|
+
"for an owner or admin, the two work tracking switches (GET /company-settings).")
|
|
111
195
|
.option("--json", "Print the result as JSON")
|
|
112
196
|
.action(async (opts) => {
|
|
113
197
|
try {
|
|
@@ -137,11 +221,24 @@ export function registerCompanyCommand(program) {
|
|
|
137
221
|
console.error(chalk.red("Failed to read company settings: no checkpointGateEnabled in the response."));
|
|
138
222
|
process.exit(1);
|
|
139
223
|
}
|
|
224
|
+
// The work tracking switches are only on the owner/admin settings
|
|
225
|
+
// route. A refused or failed read is reported as unknown, not guessed.
|
|
226
|
+
const workTracking = await readWorkTrackingSettings(token, companyUid);
|
|
140
227
|
if (opts.json) {
|
|
141
|
-
console.log(JSON.stringify({
|
|
228
|
+
console.log(JSON.stringify({
|
|
229
|
+
company: companySlug,
|
|
230
|
+
checkpointGateEnabled: enabled,
|
|
231
|
+
workRegistryEnabled: workTracking?.workRegistryEnabled ?? null,
|
|
232
|
+
workMeshLiveEnabled: workTracking?.workMeshLiveEnabled ?? null,
|
|
233
|
+
}));
|
|
142
234
|
}
|
|
143
235
|
else {
|
|
144
236
|
console.log(`checkpointGateEnabled=${enabled}`);
|
|
237
|
+
for (const key of ["workRegistryEnabled", "workMeshLiveEnabled"]) {
|
|
238
|
+
console.log(workTracking
|
|
239
|
+
? `${key}=${workTracking[key]}`
|
|
240
|
+
: `${key}=unknown (only the company owner or an admin can read this setting)`);
|
|
241
|
+
}
|
|
145
242
|
}
|
|
146
243
|
}
|
|
147
244
|
catch (err) {
|
package/dist/commands/daemon.js
CHANGED
|
@@ -29,6 +29,7 @@ import { MACHINE_TYPE_MARKER_PATH, detectMachineType, homeFromPasswd, } from "..
|
|
|
29
29
|
import { daemonPaths } from "../lib/daemon/paths.js";
|
|
30
30
|
import { processCommandLine } from "../lib/daemon/lock.js";
|
|
31
31
|
import { writeControlRequest } from "../lib/daemon/requests.js";
|
|
32
|
+
import { runDaemonCall } from "../lib/daemon/command-call.js";
|
|
32
33
|
import { isSyncRunnerCommandLine, readWatchRunnerOwnerStatus, watchRunnerOwnerStatusPath } from "../lib/daemon/sync-runner.js";
|
|
33
34
|
import { getSyncModeForCompany, setSyncMode } from "./sync-mode.js";
|
|
34
35
|
import { requireAnywhereRuntime } from "./anywhere-runtime-flag.js";
|
|
@@ -857,17 +858,7 @@ export function registerDaemonCommand(program, over = {}) {
|
|
|
857
858
|
const timeoutMs = Number(opts.timeout ?? (op === "policy.check" ? "40000" : "20000"));
|
|
858
859
|
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
|
|
859
860
|
throw new Error("--timeout must be a positive number of milliseconds");
|
|
860
|
-
|
|
861
|
-
try {
|
|
862
|
-
const result = await hqdRequest(op, args, { socketPath: hqdSocketPath(d.home, d.env), timeoutMs });
|
|
863
|
-
d.out(JSON.stringify(result, null, 2));
|
|
864
|
-
}
|
|
865
|
-
catch (err) {
|
|
866
|
-
if (!(err instanceof HqdClientError))
|
|
867
|
-
throw err;
|
|
868
|
-
d.out(JSON.stringify({ error: { code: err.code, message: err.message } }, null, 2));
|
|
869
|
-
process.exitCode = 1;
|
|
870
|
-
}
|
|
861
|
+
await runResidentCommandWithPackageLease("daemon-call", () => runDaemonCall(op, args, timeoutMs, d));
|
|
871
862
|
}));
|
|
872
863
|
daemon
|
|
873
864
|
.command("status")
|
package/dist/commands/dm.js
CHANGED
|
@@ -614,11 +614,20 @@ async function runChannelSend(channelName, message, opts) {
|
|
|
614
614
|
// Send the human-readable form: the quotes only existed for parsing.
|
|
615
615
|
if (mentions.length > 0)
|
|
616
616
|
body = stripMentionQuotes(body);
|
|
617
|
+
let audience;
|
|
618
|
+
if (opts.audience !== undefined && opts.audience !== "") {
|
|
619
|
+
if (!DM_AUDIENCE_VALUES.includes(opts.audience)) {
|
|
620
|
+
throw new Error(`Invalid --audience '${opts.audience}': must be human, agent, or both.`);
|
|
621
|
+
}
|
|
622
|
+
audience = opts.audience;
|
|
623
|
+
}
|
|
617
624
|
const payload = { body };
|
|
618
625
|
if (mentions.length > 0)
|
|
619
626
|
payload.mentions = mentions;
|
|
620
627
|
if (rootEventId)
|
|
621
628
|
payload.rootEventId = rootEventId;
|
|
629
|
+
if (audience)
|
|
630
|
+
payload.audience = audience;
|
|
622
631
|
const sendRes = await vaultApiFetch({
|
|
623
632
|
token,
|
|
624
633
|
path: `/v1/notify/channels/${encodeURIComponent(channel.channelId)}/messages`,
|
|
@@ -1327,7 +1336,7 @@ export function registerDmCommand(program) {
|
|
|
1327
1336
|
.option("--details-file <path>", "Read the details from a file (1:1 DMs only)")
|
|
1328
1337
|
.option("--at <iso>", "Schedule delivery at an ISO8601 time (store-and-forward; delivered within ~60s of the time; 1:1 DMs only)")
|
|
1329
1338
|
.option("--in <duration>", "Schedule delivery after a relative delay: 30s, 10m, 2h, 1d (1:1 DMs only)")
|
|
1330
|
-
.option("--audience <human|agent|both>", "Tag who this message is for: human (a person must read it), agent (progress/status, hidden from humans by default), or both
|
|
1339
|
+
.option("--audience <human|agent|both>", "Tag who this message is for: human (a person must read it), agent (progress/status, hidden from humans by default), or both")
|
|
1331
1340
|
.action(async (recipient, message, opts) => {
|
|
1332
1341
|
await runDmSend(recipient, message, opts);
|
|
1333
1342
|
});
|
|
@@ -272,6 +272,7 @@ export interface Ctx {
|
|
|
272
272
|
command: string;
|
|
273
273
|
timeoutSeconds?: number;
|
|
274
274
|
waitMs?: number;
|
|
275
|
+
beforeWait?: () => Promise<void>;
|
|
275
276
|
}) => Promise<OutpostDispatchResult>;
|
|
276
277
|
backfillOutpostIdentity: (expectedId: string) => "created" | "unchanged";
|
|
277
278
|
fetchText: (url: string) => Promise<string>;
|
package/dist/commands/lanes.d.ts
CHANGED
|
@@ -86,6 +86,7 @@ export interface LanesCommandDeps {
|
|
|
86
86
|
command: string;
|
|
87
87
|
timeoutSeconds?: number;
|
|
88
88
|
waitMs?: number;
|
|
89
|
+
beforeWait?: () => Promise<void>;
|
|
89
90
|
}) => Promise<OutpostDispatchResult>;
|
|
90
91
|
/** Test seam for the atomic, non-overwriting marker repair. */
|
|
91
92
|
backfillOutpostIdentity?: (expectedId: string) => "created" | "unchanged";
|
package/dist/commands/lanes.js
CHANGED
|
@@ -4317,11 +4317,22 @@ async function dispatchOutpostLaneCommand(ctx, lane, action, options, behavior =
|
|
|
4317
4317
|
let dispatched;
|
|
4318
4318
|
let grantContextRejected = false;
|
|
4319
4319
|
let failedResumeOptionRejected = false;
|
|
4320
|
+
let outpostWaitLeasePreparationStarted = false;
|
|
4320
4321
|
try {
|
|
4321
4322
|
const dispatchCommand = (contexts) => ctx.dispatchOutpostExec({
|
|
4322
4323
|
outpostId,
|
|
4323
4324
|
timeoutSeconds: Math.ceil(waitMs / 1000),
|
|
4324
4325
|
waitMs,
|
|
4326
|
+
...(action === "message" || action === "resume"
|
|
4327
|
+
? {
|
|
4328
|
+
beforeWait: async () => {
|
|
4329
|
+
if (outpostWaitLeasePreparationStarted)
|
|
4330
|
+
return;
|
|
4331
|
+
outpostWaitLeasePreparationStarted = true;
|
|
4332
|
+
await runResidentCommandWithPackageLease("outpost-wait", async () => undefined);
|
|
4333
|
+
},
|
|
4334
|
+
}
|
|
4335
|
+
: {}),
|
|
4325
4336
|
command: buildOutpostLaneCommand({
|
|
4326
4337
|
action: action === "grant"
|
|
4327
4338
|
? "grant-target"
|
package/dist/commands/mesh.js
CHANGED
|
@@ -1424,7 +1424,9 @@ async function runContextRequeue(opts) {
|
|
|
1424
1424
|
}
|
|
1425
1425
|
const scope = errorCode === null
|
|
1426
1426
|
? "all quarantine reasons"
|
|
1427
|
-
:
|
|
1427
|
+
: errorCode === undefined
|
|
1428
|
+
? "lastErrorCode=AUTH_DENIED or refused while work tracking was off"
|
|
1429
|
+
: `lastErrorCode=${errorCode}`;
|
|
1428
1430
|
console.log(`Requeued ${requeued.length} quarantined outbox operation${requeued.length === 1 ? "" : "s"} (${scope}). The mesh daemon will retry them on its next replay.`);
|
|
1429
1431
|
}
|
|
1430
1432
|
async function runContextUntracked(sessionId, opts) {
|
|
@@ -2016,7 +2018,9 @@ export function registerMeshCommand(program) {
|
|
|
2016
2018
|
.action((opts) => wrap(() => runContextCorrect(opts))());
|
|
2017
2019
|
context
|
|
2018
2020
|
.command("requeue")
|
|
2019
|
-
.description("Requeue quarantined outbox operations (default:
|
|
2021
|
+
.description("Requeue quarantined outbox operations (default: AUTH_DENIED - work-mesh-live gap 10 recovery - " +
|
|
2022
|
+
"plus sessions refused while work tracking was off). " +
|
|
2023
|
+
"Run once after the company owner turns work tracking on")
|
|
2020
2024
|
.option("--all", "Requeue every quarantined op regardless of lastErrorCode")
|
|
2021
2025
|
.option("--error-code <code>", "Requeue quarantined ops with this lastErrorCode")
|
|
2022
2026
|
.option("--json", "Print machine-readable JSON")
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
* from each pack's package.yaml; rationale lives in the layout-fix PR.)
|
|
35
35
|
*/
|
|
36
36
|
import { type KeyObject } from 'node:crypto';
|
|
37
|
+
import { type ResidentCommandLeaseOptions } from '../utils/resident-package-preload.js';
|
|
37
38
|
import { type SecretResolver } from './mcp-registration.js';
|
|
38
39
|
import type { PackManifest } from '../types.js';
|
|
39
40
|
export interface ResolveLatestOptions {
|
|
@@ -447,6 +448,7 @@ export interface InstallPackOptions {
|
|
|
447
448
|
*/
|
|
448
449
|
requireSignature?: boolean;
|
|
449
450
|
}
|
|
451
|
+
export declare function runPackInstallWithLease<T>(run: () => Promise<T>, leaseOptions?: ResidentCommandLeaseOptions): Promise<T>;
|
|
450
452
|
export declare function installPack(source: string, opts?: InstallPackOptions): Promise<void>;
|
|
451
453
|
export {};
|
|
452
454
|
//# sourceMappingURL=pack-install.d.ts.map
|
|
@@ -50,6 +50,7 @@ import { codexTargets } from '../lib/install/codex-targets.js';
|
|
|
50
50
|
import { readHqVersion, routeContribution, listInstalledPacks, mcpServerNameForContribution } from '../utils/pack-contributions.js';
|
|
51
51
|
import { CONTRIBUTION_TABLE, payloadFor } from '../utils/contribution-table.js';
|
|
52
52
|
import { safeExtractTarball } from './safe-extract.js';
|
|
53
|
+
import { runResidentCommandWithPackageLease } from '../utils/resident-package-preload.js';
|
|
53
54
|
import { getCompanyUid, vaultApiFetch, vaultApiFetchPublic, } from '../utils/vault-api.js';
|
|
54
55
|
import { ensureCognitoToken } from '../utils/cognito-session.js';
|
|
55
56
|
import { formatApiKeyCapabilityDenial, peekHqApiKey, } from '../utils/resolve-vault-credential.js';
|
|
@@ -1677,7 +1678,13 @@ export function runScanPackages(hqRoot, opts = {}) {
|
|
|
1677
1678
|
console.log(chalk.yellow(' scan-packages.sh exited non-zero; see output above.'));
|
|
1678
1679
|
}
|
|
1679
1680
|
}
|
|
1681
|
+
export function runPackInstallWithLease(run, leaseOptions) {
|
|
1682
|
+
return runResidentCommandWithPackageLease("pack-install", run, leaseOptions);
|
|
1683
|
+
}
|
|
1680
1684
|
export async function installPack(source, opts = {}) {
|
|
1685
|
+
return runPackInstallWithLease(() => installPackWithoutLease(source, opts));
|
|
1686
|
+
}
|
|
1687
|
+
async function installPackWithoutLease(source, opts) {
|
|
1681
1688
|
// NOTE: the HQ_API_KEY fail-closed gate is NOT enforced here. `installPack`
|
|
1682
1689
|
// is a shared primitive called both by the top-level `hq install` CLI route
|
|
1683
1690
|
// (where Cognito-only is the right gate — checked there instead) AND by
|
|
@@ -5,5 +5,7 @@
|
|
|
5
5
|
* If slug given: update only that package.
|
|
6
6
|
*/
|
|
7
7
|
import { Command } from 'commander';
|
|
8
|
+
import { type ResidentCommandLeaseOptions } from '../utils/resident-package-preload.js';
|
|
8
9
|
export declare function registerPackageUpdateCommand(parent: Command): void;
|
|
10
|
+
export declare function runPackageUpdateWithLease<T>(run: () => Promise<T>, leaseOptions?: ResidentCommandLeaseOptions): Promise<T>;
|
|
9
11
|
//# sourceMappingURL=pkg-update.d.ts.map
|
|
@@ -9,6 +9,7 @@ import * as os from 'os';
|
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import { parseUserYaml } from '../utils/user-yaml-error.js';
|
|
11
11
|
import { execSync } from 'child_process';
|
|
12
|
+
import { runResidentCommandWithPackageLease } from '../utils/resident-package-preload.js';
|
|
12
13
|
import chalk from 'chalk';
|
|
13
14
|
import { ensureCognitoToken } from '../utils/cognito-session.js';
|
|
14
15
|
import { resolveDefaultHqRoot } from '../utils/cognito-session.js';
|
|
@@ -21,7 +22,7 @@ export function registerPackageUpdateCommand(parent) {
|
|
|
21
22
|
.description('Check for and apply package updates')
|
|
22
23
|
.action(async (slug) => {
|
|
23
24
|
try {
|
|
24
|
-
await updatePackages(slug);
|
|
25
|
+
await runPackageUpdateWithLease(() => updatePackages(slug));
|
|
25
26
|
}
|
|
26
27
|
catch (error) {
|
|
27
28
|
console.error(chalk.red('Update failed:'), error instanceof Error ? error.message : 'Unknown error');
|
|
@@ -29,6 +30,9 @@ export function registerPackageUpdateCommand(parent) {
|
|
|
29
30
|
}
|
|
30
31
|
});
|
|
31
32
|
}
|
|
33
|
+
export function runPackageUpdateWithLease(run, leaseOptions) {
|
|
34
|
+
return runResidentCommandWithPackageLease("pkg-update", run, leaseOptions);
|
|
35
|
+
}
|
|
32
36
|
async function updatePackages(slug) {
|
|
33
37
|
const hqRoot = resolveDefaultHqRoot({ onMissing: 'throw' });
|
|
34
38
|
const entries = readRegistry(hqRoot);
|
package/dist/commands/secrets.js
CHANGED
|
@@ -10,6 +10,7 @@ import { SECRET_NAME_PATTERN, GROUP_ID_PATTERN, EMAIL_PATTERN } from "./_pattern
|
|
|
10
10
|
import { describeSecretsScope, formatSecretSaved, formatSecretsListEmpty, formatSecretsListHeader, } from "./secrets-scope.js";
|
|
11
11
|
import { vaultApiFetch, getCompanyUid, getEntityUid, looksLikeCompanyUid, } from "../utils/vault-api.js";
|
|
12
12
|
import { formatApiKeyCapabilityDenial, requireApiKeyCapability, resolveVaultCredentialForCapability, } from "../utils/resolve-vault-credential.js";
|
|
13
|
+
import { runSandboxJobAfterSubmission } from "../utils/secrets-sandbox-resident.js";
|
|
13
14
|
export { vaultApiFetch, getCompanyUid, getEntityUid };
|
|
14
15
|
/**
|
|
15
16
|
* Mirrors `RESOURCE_SURFACES` in hq-pro
|
|
@@ -1061,9 +1062,7 @@ export function registerSecretsCommand(program) {
|
|
|
1061
1062
|
secretNames: keys,
|
|
1062
1063
|
command,
|
|
1063
1064
|
});
|
|
1064
|
-
const job =
|
|
1065
|
-
? await client.getJob(token, started.jobId)
|
|
1066
|
-
: await client.pollJob(token, started.jobId);
|
|
1065
|
+
const job = await runSandboxJobAfterSubmission(client, token, started);
|
|
1067
1066
|
renderSandboxJobResult(job, keys);
|
|
1068
1067
|
const exitCode = typeof job.exitCode === "number" ? job.exitCode : undefined;
|
|
1069
1068
|
if (job.success === false || (exitCode !== undefined && exitCode !== 0) || job.status === "failed") {
|
|
@@ -237,7 +237,7 @@ export function buildAgentMcpTools(clients) {
|
|
|
237
237
|
const token = await clients.getToken();
|
|
238
238
|
const res = await clients.apiJson(token, `/v1/notify/channels/${encodeURIComponent(to)}/messages`, {
|
|
239
239
|
method: "POST",
|
|
240
|
-
body: { body: message },
|
|
240
|
+
body: { body: message, ...(audience ? { audience } : {}) },
|
|
241
241
|
});
|
|
242
242
|
if (res.status < 200 || res.status >= 300) {
|
|
243
243
|
return errorResult(`Channel send failed (${res.status}): ${describeError(res.body)}`);
|
package/dist/lib/bot/api.d.ts
CHANGED
package/dist/lib/bot/api.js
CHANGED
|
@@ -195,6 +195,8 @@ export class BotApi {
|
|
|
195
195
|
const payload = { body: input.body };
|
|
196
196
|
if (input.rootEventId)
|
|
197
197
|
payload.rootEventId = input.rootEventId;
|
|
198
|
+
if (input.audience)
|
|
199
|
+
payload.audience = input.audience;
|
|
198
200
|
const { body } = await this.call(`/v1/notify/channels/${encodeURIComponent(input.channelId)}/messages`, { method: "POST", body: payload });
|
|
199
201
|
return body;
|
|
200
202
|
}
|
|
@@ -28,13 +28,10 @@ export declare const PROGRESS_MIN_GAP_MS = 4000;
|
|
|
28
28
|
export declare const WORKING_NOTICE_MS = 60000;
|
|
29
29
|
export declare const WORKING_NOTICE_TEXT = "Working on it \u2014 I'll reply here when it's done.";
|
|
30
30
|
export interface ProgressPosterOptions {
|
|
31
|
-
/** Post
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
* Use to tag the final reply differently from in-between progress messages.
|
|
36
|
-
*/
|
|
37
|
-
sendFinal?: (body: string) => Promise<boolean>;
|
|
31
|
+
/** Post a live progress beat while the turn is still running. */
|
|
32
|
+
sendProgress: (body: string) => Promise<boolean>;
|
|
33
|
+
/** Post terminal content that the person needs to read. */
|
|
34
|
+
sendToPerson: (body: string) => Promise<boolean>;
|
|
38
35
|
now?: () => number;
|
|
39
36
|
setTimer?: (fn: () => void, ms: number) => unknown;
|
|
40
37
|
clearTimer?: (handle: unknown) => void;
|
|
@@ -63,8 +60,8 @@ export declare function normalizeForCompare(text: string): string;
|
|
|
63
60
|
/** Matches {"action":"no_reply"} anywhere in a model reply, with or without preamble text. */
|
|
64
61
|
export declare function containsNoReplySentinel(text: string): boolean;
|
|
65
62
|
export declare class ProgressPoster {
|
|
66
|
-
private readonly
|
|
67
|
-
private readonly
|
|
63
|
+
private readonly sendProgress;
|
|
64
|
+
private readonly sendToPerson;
|
|
68
65
|
private readonly now;
|
|
69
66
|
private readonly setTimer;
|
|
70
67
|
private readonly clearTimer;
|
|
@@ -95,6 +92,8 @@ export declare class ProgressPoster {
|
|
|
95
92
|
* deliveries posted the placeholder right after a real message.
|
|
96
93
|
*/
|
|
97
94
|
private queued;
|
|
95
|
+
/** Posts queued for the person, excluding agent-lane status beats. */
|
|
96
|
+
private personQueued;
|
|
98
97
|
constructor(opts: ProgressPosterOptions);
|
|
99
98
|
/** Arm the one-time "working on it" note. Call when the turn starts. */
|
|
100
99
|
start(): void;
|
|
@@ -109,11 +108,9 @@ export declare class ProgressPoster {
|
|
|
109
108
|
/** True once any message from the model was said this turn (not counting the notice). */
|
|
110
109
|
get saidAnything(): boolean;
|
|
111
110
|
/**
|
|
112
|
-
* The turn succeeded: post
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* When `sendFinal` was provided, progress items flush through `send` and the
|
|
116
|
-
* final reply goes through `sendFinal` — keeping their audience tags distinct.
|
|
111
|
+
* The turn succeeded: post pending human-facing text, then a human-lane
|
|
112
|
+
* terminal message when the final adds something. Agent-lane status beats
|
|
113
|
+
* alone still receive a human-lane fallback before the turn closes.
|
|
117
114
|
*/
|
|
118
115
|
finish(finalText: string): Promise<void>;
|
|
119
116
|
/**
|
|
@@ -125,6 +122,7 @@ export declare class ProgressPoster {
|
|
|
125
122
|
private scheduleFlush;
|
|
126
123
|
private flushNow;
|
|
127
124
|
private enqueue;
|
|
125
|
+
private enqueueToPerson;
|
|
128
126
|
private enqueueWith;
|
|
129
127
|
private cancelFlush;
|
|
130
128
|
private cancelNotice;
|