@indigoai-us/hq-cli 5.342.12 → 5.342.14
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 +17 -0
- package/assets/scaffold/core/scripts/hq-delegate-grant.sh +9 -0
- package/assets/scaffold/core/scripts/hq-delegate-send.sh +9 -0
- package/assets/scaffold/core/scripts/hq-job-probe.sh +9 -0
- package/assets/scaffold/core/scripts/jobs-validate.sh +9 -0
- package/dist/commands/agent-kit.d.ts +2 -0
- package/dist/commands/agent-kit.js +23 -17
- package/dist/commands/agent-mcp.d.ts +2 -0
- package/dist/commands/agent-mcp.js +21 -15
- package/dist/commands/core-delegate-w1b.js +19 -10
- package/dist/commands/core-delegate.d.ts +2 -0
- package/dist/commands/core-delegate.js +16 -4
- package/dist/commands/core-job-probe-native.d.ts +4 -1
- package/dist/commands/core-job-probe-native.js +62 -14
- package/dist/commands/core-job-run-native.js +14 -2
- package/dist/commands/core-jobs-native.js +2 -1
- package/dist/commands/core-ontology-native.js +18 -2
- package/dist/commands/core-worker-share-native.js +2 -1
- package/dist/commands/lanes-message.d.ts +20 -2
- package/dist/commands/lanes-message.js +99 -38
- package/dist/commands/lanes-shared.d.ts +1 -0
- package/dist/commands/lanes.d.ts +4 -0
- package/dist/commands/lanes.js +24 -30
- package/dist/commands/mesh.js +2 -1
- package/dist/commands/monitor.d.ts +14 -1
- package/dist/commands/monitor.js +43 -14
- package/dist/lib/core-utils/shell-display-path.d.ts +3 -0
- package/dist/lib/core-utils/shell-display-path.js +12 -0
- package/dist/lib/doctor/checks/anywhere.js +11 -6
- 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-audit.d.ts +3 -0
- package/dist/lib/lanes/keep-alive-audit.js +59 -11
- package/dist/lib/lanes/reconcile.js +46 -3
- package/dist/lib/lanes/types.d.ts +2 -1
- package/dist/utils/resident-package-preload.d.ts +8 -1
- package/dist/utils/resident-package-preload.js +68 -0
- package/dist/utils/run-bundled-script.d.ts +2 -0
- package/dist/utils/run-bundled-script.js +1 -0
- package/dist/utils/windows-spawn.d.ts +2 -0
- package/dist/utils/windows-spawn.js +6 -0
- package/docs/anywhere-runtime.md +3 -1
- package/package.json +4 -4
- package/dist/lib/db/remote-engine.d.ts +0 -58
- package/dist/lib/db/remote-engine.js +0 -87
- package/dist/lib/db/remote-sql.d.ts +0 -22
- package/dist/lib/db/remote-sql.js +0 -36
|
@@ -3,8 +3,10 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
import * as path from "node:path";
|
|
6
|
+
import { resolveWindowsExecutable } from "../lib/bot/runtime/windows.js";
|
|
6
7
|
import { runBundledScript } from "../utils/run-bundled-script.js";
|
|
7
8
|
import { resolveBundledAsset } from "../utils/hq-roots.js";
|
|
9
|
+
import { planResolvedCommandSpawn } from "../utils/windows-spawn.js";
|
|
8
10
|
import { describeCoreCommand } from "./core-command-catalog.js";
|
|
9
11
|
import { runKnowledgePrefs } from "./core-knowledge-prefs.js";
|
|
10
12
|
const FLAG = "core-native-ontology";
|
|
@@ -55,10 +57,23 @@ export function runOntologyNativeFast(args, _stdin, cwd, hqRoot, commandName) {
|
|
|
55
57
|
}
|
|
56
58
|
function runHq(args, output = "capture") {
|
|
57
59
|
const executable = process.env.HQ_BIN || "hq";
|
|
58
|
-
const
|
|
60
|
+
const resolvedExecutable = process.platform === "win32" && !path.isAbsolute(executable) && !executable.includes(path.sep)
|
|
61
|
+
? resolveWindowsExecutable(executable, process.env, (candidate) => {
|
|
62
|
+
try {
|
|
63
|
+
return fs.statSync(candidate).isFile();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}, process.cwd()) ?? executable
|
|
69
|
+
: executable;
|
|
70
|
+
const plan = planResolvedCommandSpawn(resolvedExecutable, args, process.env);
|
|
71
|
+
const result = spawnSync(plan.cmd, plan.args, {
|
|
59
72
|
cwd: process.cwd(),
|
|
60
73
|
env: process.env,
|
|
61
74
|
encoding: "utf8",
|
|
75
|
+
shell: plan.shell,
|
|
76
|
+
...(plan.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}),
|
|
62
77
|
stdio: output === "ignore" ? ["ignore", "ignore", "ignore"] : ["ignore", "pipe", "ignore"],
|
|
63
78
|
});
|
|
64
79
|
return { status: result.status, stdout: typeof result.stdout === "string" ? result.stdout : "" };
|
|
@@ -522,7 +537,8 @@ export function gardenCommand(args, defaultRoot) {
|
|
|
522
537
|
source_ref: JSON.stringify(fm.source_ref || ""), created_at: String(fm.created_at || isoNow()),
|
|
523
538
|
}, body, dryRun);
|
|
524
539
|
report.signals_promoted += 1;
|
|
525
|
-
|
|
540
|
+
const outputPath = path.relative(companyDir, outputFile);
|
|
541
|
+
index.push({ signal_id: id, type, audience_key: key, path: process.platform === "win32" ? outputPath.replaceAll("\\", "/") : outputPath });
|
|
526
542
|
if (key !== "company") {
|
|
527
543
|
const audienceFile = path.join(scopeDirectory, "_audience.yaml");
|
|
528
544
|
if (!fs.existsSync(audienceFile) && !dryRun) {
|
|
@@ -56,7 +56,8 @@ function isRegularFile(filePath, fileSystem) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
function readLink(filePath, fileSystem) {
|
|
59
|
-
|
|
59
|
+
const target = fileSystem.readlinkSync(filePath);
|
|
60
|
+
return process.platform === "win32" ? target.replaceAll("\\", "/") : target;
|
|
60
61
|
}
|
|
61
62
|
function sameBytes(leftPath, rightPath, fileSystem) {
|
|
62
63
|
try {
|
|
@@ -1,6 +1,24 @@
|
|
|
1
|
-
import { type Ctx, type LaneMessageHandlerDeps, type LaneMessageOptions } from "./lanes-shared.js";
|
|
1
|
+
import { type Ctx, type LaneMessageHandlerDeps, type LaneMessageOptions, type LaneMessageResponse } from "./lanes-shared.js";
|
|
2
|
+
export interface MonitorLaneMessagePayload {
|
|
3
|
+
text: string;
|
|
4
|
+
monitor_id: string;
|
|
5
|
+
description: string;
|
|
6
|
+
sequence: number;
|
|
7
|
+
}
|
|
8
|
+
export type MonitorLaneMessageResult = {
|
|
9
|
+
ok: true;
|
|
10
|
+
response: LaneMessageResponse | undefined;
|
|
11
|
+
} | {
|
|
12
|
+
ok: false;
|
|
13
|
+
error: unknown;
|
|
14
|
+
errorCode: string;
|
|
15
|
+
message: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function parseMonitorLaneMessagePayload(input: unknown): MonitorLaneMessagePayload;
|
|
18
|
+
export declare function deliverMonitorLaneMessage(ctx: Ctx, laneId: string, input: unknown, runMessage: (ctx: Ctx, laneId: string, options: LaneMessageOptions) => Promise<LaneMessageResponse | undefined>): Promise<MonitorLaneMessageResult>;
|
|
2
19
|
export declare function createLaneMessageHandlers(deps: LaneMessageHandlerDeps): {
|
|
3
|
-
runMessage: (ctx: Ctx, laneId: string, opts: LaneMessageOptions) => Promise<
|
|
20
|
+
runMessage: (ctx: Ctx, laneId: string, opts: LaneMessageOptions) => Promise<LaneMessageResponse | undefined>;
|
|
21
|
+
deliverMonitorLaneMessage: (ctx: Ctx, laneId: string, input: unknown) => Promise<MonitorLaneMessageResult>;
|
|
4
22
|
recoverQueuedMessages: (ctx: Ctx, laneId: string) => Promise<{
|
|
5
23
|
action: "none" | "resumed" | "undeliverable";
|
|
6
24
|
message_count: number;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { appendCappedHistory, appendDropboxMessage, deliveryRefusalReason, dropboxInboxPath, laneAcceptsOperatorMessage, laneDeliveryMechanism, operatorMessageRefusalReason, providerSessionPortable, providerSupportsSessionResume, readLane, sessionNotPortableMessage, validateProjectStories, withLaneAdmissionLock } from "../lib/lanes/index.js";
|
|
4
|
-
import { LanesError } from "../lib/lanes/errors.js";
|
|
4
|
+
import { isLanesError, LanesError } from "../lib/lanes/errors.js";
|
|
5
|
+
import { CompanySelectionError } from "../utils/company-selection-error.js";
|
|
5
6
|
import { parseCliEffort } from "../lib/lanes/effort.js";
|
|
6
7
|
import { parseOutpostHireGrantContext, sameHireGrantSenior } from "../lib/lanes/hire-grant-dispatch.js";
|
|
7
8
|
import { dispatchLaneDelivery } from "../lib/lanes/delivery-core.js";
|
|
@@ -15,6 +16,60 @@ import { readLanesRegistryFlag } from "../lib/lanes/registry-flag.js";
|
|
|
15
16
|
import { lowDiskGuardEnabledForLane } from "../lib/lanes/disk-guard.js";
|
|
16
17
|
import { resolveLaneCompany } from "../lib/lanes/lane-company.js";
|
|
17
18
|
import { accountMoveSummary, accountRequestKeepsCurrentLane, assertCurrentResumeAccountAvailable, callerMatchesSessionSenior, recordedResumeEffort, resetKeepAliveProgress, resolveResumeEffort } from "./lanes-shared.js";
|
|
19
|
+
export function parseMonitorLaneMessagePayload(input) {
|
|
20
|
+
let payload = input;
|
|
21
|
+
if (typeof input === "string") {
|
|
22
|
+
try {
|
|
23
|
+
payload = JSON.parse(input);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
throw new LanesError("monitor_lane_payload_invalid", `Monitor lane delivery payload is invalid JSON: ${err instanceof Error ? err.message : String(err)}.`, {});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
30
|
+
throw new LanesError("monitor_lane_payload_invalid", "Monitor lane delivery payload must be an object.", {});
|
|
31
|
+
}
|
|
32
|
+
const value = payload;
|
|
33
|
+
if (typeof value.text !== "string" ||
|
|
34
|
+
typeof value.monitor_id !== "string" ||
|
|
35
|
+
typeof value.description !== "string" ||
|
|
36
|
+
!Number.isInteger(value.sequence) ||
|
|
37
|
+
Number(value.sequence) < 1) {
|
|
38
|
+
throw new LanesError("monitor_lane_payload_invalid", "Monitor lane delivery payload is missing text, monitor metadata, or sequence.", {});
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
text: value.text,
|
|
42
|
+
monitor_id: value.monitor_id,
|
|
43
|
+
description: value.description,
|
|
44
|
+
sequence: Number(value.sequence),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export async function deliverMonitorLaneMessage(ctx, laneId, input, runMessage) {
|
|
48
|
+
try {
|
|
49
|
+
const payload = parseMonitorLaneMessagePayload(input);
|
|
50
|
+
const response = await runMessage(ctx, laneId, {
|
|
51
|
+
text: payload.text,
|
|
52
|
+
monitorEvent: {
|
|
53
|
+
monitor_id: payload.monitor_id,
|
|
54
|
+
description: payload.description,
|
|
55
|
+
sequence: payload.sequence,
|
|
56
|
+
},
|
|
57
|
+
silent: true,
|
|
58
|
+
});
|
|
59
|
+
return { ok: true, response };
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
const commandError = error instanceof CompanySelectionError
|
|
63
|
+
? new LanesError("company_selection_failed", error.message)
|
|
64
|
+
: error;
|
|
65
|
+
return {
|
|
66
|
+
ok: false,
|
|
67
|
+
error: commandError,
|
|
68
|
+
errorCode: isLanesError(commandError) ? commandError.error : "internal",
|
|
69
|
+
message: commandError instanceof Error ? commandError.message : String(commandError),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
18
73
|
export function createLaneMessageHandlers(deps) {
|
|
19
74
|
const { archiveResumeMessage, assertLaneRunsHereForAdmission, assertLaneRunsHereForOperatorMutation, assessLaneAdmission, casUpdateLane, dispatchOutpostLaneCommand, dispatchPrimaryLaneMessage, drainHookStatusFor, laneIsHostedHere, laneWithRecoveredProviderSession, loadAllLanes, mintMessageId, persistClaudeAccountSelection, prepareAccountMove, printJson, recordResumeSetup, resolveActiveQuestionCompany, resolveResumeProfile, selectAutomaticClaudeResumeAccount, validateResumeProfileModel, withResumeHireAdmission } = deps;
|
|
20
75
|
function currentSuccessorOf(lane, lanes, lineageAware, companyForLane) {
|
|
@@ -843,43 +898,45 @@ export function createLaneMessageHandlers(deps) {
|
|
|
843
898
|
? `The worker has made no tool call since ${next.stalled_at ?? "an unknown time"} (${next.stalled_reason ?? "stalled"}); delivery waits on its next tool call.`
|
|
844
899
|
: null,
|
|
845
900
|
].filter((message) => message !== undefined && message !== null).join(" ") || null;
|
|
901
|
+
const response = {
|
|
902
|
+
ok: true,
|
|
903
|
+
action: "message",
|
|
904
|
+
lane_id: laneId,
|
|
905
|
+
message_id: messageId,
|
|
906
|
+
accepted: true,
|
|
907
|
+
delivered: false,
|
|
908
|
+
delivery: mechanism,
|
|
909
|
+
delivered_to: { host: lane.host.id, lane_id: laneId, mechanism },
|
|
910
|
+
delivery_status: deliveryStatus,
|
|
911
|
+
...(queuedOnQuotaHold ? {
|
|
912
|
+
queued_reason: "account_quota_held",
|
|
913
|
+
quota_hold: {
|
|
914
|
+
reason: "account_quota_held",
|
|
915
|
+
quota_reset_at: quotaHoldDeferred?.quota_reset_at ?? null,
|
|
916
|
+
model: quotaHoldDeferred?.model ?? null,
|
|
917
|
+
},
|
|
918
|
+
} : {}),
|
|
919
|
+
inbox_path: mechanism === "dropbox" ? dropboxInboxPath(hqRoot, laneId) : null,
|
|
920
|
+
drain_hook: drainHook,
|
|
921
|
+
warning,
|
|
922
|
+
...(questionCancellation === null ? {} : {
|
|
923
|
+
cancelled_questions: questionCancellation.cancelled_question_ids,
|
|
924
|
+
question_cancellation_failures: questionCancellation.failures,
|
|
925
|
+
}),
|
|
926
|
+
resumed_session_id: resumed?.last_resume?.session_id ?? null,
|
|
927
|
+
compaction: resumed?.last_compaction && resumed.last_compaction.resume_at === resumed.last_resume?.at
|
|
928
|
+
? resumed.last_compaction
|
|
929
|
+
: null,
|
|
930
|
+
account_move: move ? accountMoveSummary(move) : null,
|
|
931
|
+
project_id: next.project_id,
|
|
932
|
+
story_id: next.story_id,
|
|
933
|
+
stories: laneStories(next),
|
|
934
|
+
story_warning: storyWarning(next) ?? null,
|
|
935
|
+
lane: next,
|
|
936
|
+
};
|
|
846
937
|
if (!opts.silent)
|
|
847
|
-
printJson(
|
|
848
|
-
|
|
849
|
-
action: "message",
|
|
850
|
-
lane_id: laneId,
|
|
851
|
-
message_id: messageId,
|
|
852
|
-
accepted: true,
|
|
853
|
-
delivered: false,
|
|
854
|
-
delivery: mechanism,
|
|
855
|
-
delivered_to: { host: lane.host.id, lane_id: laneId, mechanism },
|
|
856
|
-
delivery_status: deliveryStatus,
|
|
857
|
-
...(queuedOnQuotaHold ? {
|
|
858
|
-
queued_reason: "account_quota_held",
|
|
859
|
-
quota_hold: {
|
|
860
|
-
reason: "account_quota_held",
|
|
861
|
-
quota_reset_at: quotaHoldDeferred?.quota_reset_at ?? null,
|
|
862
|
-
model: quotaHoldDeferred?.model ?? null,
|
|
863
|
-
},
|
|
864
|
-
} : {}),
|
|
865
|
-
inbox_path: mechanism === "dropbox" ? dropboxInboxPath(hqRoot, laneId) : null,
|
|
866
|
-
drain_hook: drainHook,
|
|
867
|
-
warning,
|
|
868
|
-
...(questionCancellation === null ? {} : {
|
|
869
|
-
cancelled_questions: questionCancellation.cancelled_question_ids,
|
|
870
|
-
question_cancellation_failures: questionCancellation.failures,
|
|
871
|
-
}),
|
|
872
|
-
resumed_session_id: resumed?.last_resume?.session_id ?? null,
|
|
873
|
-
compaction: resumed?.last_compaction && resumed.last_compaction.resume_at === resumed.last_resume?.at
|
|
874
|
-
? resumed.last_compaction
|
|
875
|
-
: null,
|
|
876
|
-
account_move: move ? accountMoveSummary(move) : null,
|
|
877
|
-
project_id: next.project_id,
|
|
878
|
-
story_id: next.story_id,
|
|
879
|
-
stories: laneStories(next),
|
|
880
|
-
story_warning: storyWarning(next) ?? null,
|
|
881
|
-
lane: next,
|
|
882
|
-
});
|
|
938
|
+
printJson(response);
|
|
939
|
+
return response;
|
|
883
940
|
}
|
|
884
941
|
catch (err) {
|
|
885
942
|
if (storySwitchRollback !== undefined && !storySwitchDeliveryStarted) {
|
|
@@ -994,6 +1051,10 @@ export function createLaneMessageHandlers(deps) {
|
|
|
994
1051
|
throw err;
|
|
995
1052
|
}
|
|
996
1053
|
}
|
|
997
|
-
return {
|
|
1054
|
+
return {
|
|
1055
|
+
runMessage,
|
|
1056
|
+
deliverMonitorLaneMessage: (ctx, laneId, input) => deliverMonitorLaneMessage(ctx, laneId, input, runMessage),
|
|
1057
|
+
recoverQueuedMessages,
|
|
1058
|
+
};
|
|
998
1059
|
}
|
|
999
1060
|
//# sourceMappingURL=lanes-message.js.map
|
|
@@ -60,6 +60,7 @@ export interface LaneMessageOptions {
|
|
|
60
60
|
/** Internal recovery claim is safe to archive once this callback runs. */
|
|
61
61
|
onAccepted?: () => void;
|
|
62
62
|
}
|
|
63
|
+
export type LaneMessageResponse = Record<string, unknown>;
|
|
63
64
|
export interface LaneResumeOptions {
|
|
64
65
|
text?: string;
|
|
65
66
|
fromFailed?: boolean;
|
package/dist/commands/lanes.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* `watch` and the monitor reminder are the line-oriented text surfaces.
|
|
7
7
|
*/
|
|
8
8
|
import { Command } from "commander";
|
|
9
|
+
import type { MonitorLaneMessagePayload, MonitorLaneMessageResult } from "./lanes-message.js";
|
|
9
10
|
import { type LanesMesh, type OutpostRouteIdentity, type SpawnLoginResult } from "./lanes-shared.js";
|
|
10
11
|
export type { LanesMesh, SpawnLoginResult } from "./lanes-shared.js";
|
|
11
12
|
export { CLAUDE_ACCOUNT_BALANCE_SIGNALS_FLAG, LANE_OUTPOST_LOAD_BALANCING_FLAG } from "./lanes-shared.js";
|
|
@@ -105,6 +106,9 @@ export interface LanesCommandDeps {
|
|
|
105
106
|
/** Test seam for the repository-merge-hold registry flag. */
|
|
106
107
|
mergeHoldEnabled?: (company: LaneCompanyRef) => boolean | Promise<boolean>;
|
|
107
108
|
}
|
|
109
|
+
export type MonitorLaneMessageApi = (laneId: string, payload: MonitorLaneMessagePayload) => Promise<MonitorLaneMessageResult>;
|
|
110
|
+
/** Build the same lane message handlers used by `hq lanes _monitor-message`, without a CLI process boundary. */
|
|
111
|
+
export declare function createMonitorLaneMessageApi(hqRoot: string, cwd: string, env?: NodeJS.ProcessEnv): MonitorLaneMessageApi;
|
|
108
112
|
export declare function parseSeniorRef(raw: string): SeniorRef;
|
|
109
113
|
export declare function parseQuestionBody(raw: unknown): QuestionBody | null;
|
|
110
114
|
/**
|
package/dist/commands/lanes.js
CHANGED
|
@@ -10,7 +10,7 @@ import { randomBytes } from "node:crypto";
|
|
|
10
10
|
import * as fs from "node:fs";
|
|
11
11
|
import * as os from "node:os";
|
|
12
12
|
import * as path from "node:path";
|
|
13
|
-
import { Option } from "commander";
|
|
13
|
+
import { Command, Option } from "commander";
|
|
14
14
|
import { createLaneAccountsHandlers } from "./lanes-accounts.js";
|
|
15
15
|
import { createLaneMessageHandlers } from "./lanes-message.js";
|
|
16
16
|
import { createLaneMoveHandlers } from "./lanes-move.js";
|
|
@@ -34,6 +34,7 @@ import { ensureCognitoToken } from "../utils/cognito-session.js";
|
|
|
34
34
|
import { withCliFeatureUsed } from "../utils/cli-telemetry.js";
|
|
35
35
|
import { resolveLanesHqRoot } from "../lib/lanes/hq-root.js";
|
|
36
36
|
import { isSsmRunCommandProcess } from "../lib/lanes/ssm-command-context.js";
|
|
37
|
+
import { runResidentCommandWithPackageLease } from "../utils/resident-package-preload.js";
|
|
37
38
|
import { readLanesFlagLocalOverride, readLanesRegistryFlag, readLanesRegistryFlagFailOff } from "../lib/lanes/registry-flag.js";
|
|
38
39
|
import { LANE_HIRE_GRANT_FINISHED_LANES_FLAG, LANE_LIST_SKIP_REMOTE_REFRESH_FLAG, LANE_MESSAGE_ROUTE_OWNER_HOST_FLAG, LANE_ORPHANED_BARE_ID_DROPBOX_REPAIR_FLAG, LANE_REUSE_REFRESHES_PROFILE_FLAG, } from "../lib/lanes/flag-keys.js";
|
|
39
40
|
import { CODEX_ROLLOUT_RETENTION_FLAG, configuredCodexRolloutHomes, lowDiskGuardEnabledForLane, retainCodexRollouts } from "../lib/lanes/disk-guard.js";
|
|
@@ -90,6 +91,20 @@ const REMOTE_MIRROR_REFRESH_BATCH_SIZE = 100;
|
|
|
90
91
|
const REMOTE_LANE_NOT_FOUND_GRACE_MS = 15 * 60_000;
|
|
91
92
|
/** The lane → mesh seam. Defined in lib/lanes/mesh-events.ts; the watcher shares it. */
|
|
92
93
|
export { emitLaneDecisionEvents };
|
|
94
|
+
const monitorLaneMessageApis = new WeakMap();
|
|
95
|
+
/** Build the same lane message handlers used by `hq lanes _monitor-message`, without a CLI process boundary. */
|
|
96
|
+
export function createMonitorLaneMessageApi(hqRoot, cwd, env = process.env) {
|
|
97
|
+
const program = new Command();
|
|
98
|
+
registerLanesCommand(program, {
|
|
99
|
+
hqRoot: () => hqRoot,
|
|
100
|
+
cwd: () => cwd,
|
|
101
|
+
env: { ...env, HQ_ROOT: hqRoot },
|
|
102
|
+
});
|
|
103
|
+
const api = monitorLaneMessageApis.get(program);
|
|
104
|
+
if (!api)
|
|
105
|
+
throw new Error("Monitor lane message handler was not registered");
|
|
106
|
+
return api;
|
|
107
|
+
}
|
|
93
108
|
function withoutProviderHome(value) {
|
|
94
109
|
if (Array.isArray(value))
|
|
95
110
|
return value.map(withoutProviderHome);
|
|
@@ -8390,6 +8405,7 @@ export function registerLanesCommand(parent, deps = {}) {
|
|
|
8390
8405
|
withResumeHireAdmission,
|
|
8391
8406
|
};
|
|
8392
8407
|
const messageHandlers = createLaneMessageHandlers(messageHandlerDeps);
|
|
8408
|
+
monitorLaneMessageApis.set(parent, (laneId, payload) => messageHandlers.deliverMonitorLaneMessage(ctx, laneId, payload));
|
|
8393
8409
|
const resumeHandlers = createLaneResumeHandlers({
|
|
8394
8410
|
onLaneWorkerStarted: deps.onLaneWorkerStarted,
|
|
8395
8411
|
archiveResumeMessage,
|
|
@@ -8681,13 +8697,13 @@ export function registerLanesCommand(parent, deps = {}) {
|
|
|
8681
8697
|
.option("--for <change-type>", "envelope | question | state", collectRepeatable, [])
|
|
8682
8698
|
.option("--timeout <seconds>", "Positive timeout in seconds")
|
|
8683
8699
|
.option("--json", "JSON output")
|
|
8684
|
-
.action(wrapText(async (opts) => watchHandlers.runWait(ctx, opts)));
|
|
8700
|
+
.action(wrapText(async (opts) => runResidentCommandWithPackageLease("lanes-watch", () => watchHandlers.runWait(ctx, opts))));
|
|
8685
8701
|
lanes
|
|
8686
8702
|
.command("watch")
|
|
8687
8703
|
.description("Watch lane state and question changes until all lanes are terminal")
|
|
8688
8704
|
.argument("<lane-id...>", "Lane ids to watch")
|
|
8689
8705
|
.option("--interval-ms <ms>", "Polling interval, bounded to 100ms–30s", "5000")
|
|
8690
|
-
.action(wrapText(async (laneIds, opts) => watchHandlers.runWatch(ctx, laneIds, opts)));
|
|
8706
|
+
.action(wrapText(async (laneIds, opts) => runResidentCommandWithPackageLease("lanes-watch", () => watchHandlers.runWatch(ctx, laneIds, opts))));
|
|
8691
8707
|
lanes
|
|
8692
8708
|
.command("monitor-check")
|
|
8693
8709
|
.description("Check that active Claude senior lanes have live Monitor watch tasks")
|
|
@@ -8809,33 +8825,11 @@ export function registerLanesCommand(parent, deps = {}) {
|
|
|
8809
8825
|
.command("_monitor-message", { hidden: true })
|
|
8810
8826
|
.argument("<lane-id>", "Lane id")
|
|
8811
8827
|
.action(wrap(async (laneId) => {
|
|
8812
|
-
const
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
catch (err) {
|
|
8818
|
-
throw new LanesError("monitor_lane_payload_invalid", `Monitor lane delivery payload is invalid JSON: ${err instanceof Error ? err.message : String(err)}.`, {});
|
|
8819
|
-
}
|
|
8820
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
8821
|
-
throw new LanesError("monitor_lane_payload_invalid", "Monitor lane delivery payload must be an object.", {});
|
|
8822
|
-
}
|
|
8823
|
-
const value = payload;
|
|
8824
|
-
if (typeof value.text !== "string" ||
|
|
8825
|
-
typeof value.monitor_id !== "string" ||
|
|
8826
|
-
typeof value.description !== "string" ||
|
|
8827
|
-
!Number.isInteger(value.sequence) ||
|
|
8828
|
-
Number(value.sequence) < 1) {
|
|
8829
|
-
throw new LanesError("monitor_lane_payload_invalid", "Monitor lane delivery payload is missing text, monitor metadata, or sequence.", {});
|
|
8830
|
-
}
|
|
8831
|
-
await messageHandlers.runMessage(ctx, laneId, {
|
|
8832
|
-
text: value.text,
|
|
8833
|
-
monitorEvent: {
|
|
8834
|
-
monitor_id: value.monitor_id,
|
|
8835
|
-
description: value.description,
|
|
8836
|
-
sequence: Number(value.sequence),
|
|
8837
|
-
},
|
|
8838
|
-
});
|
|
8828
|
+
const result = await messageHandlers.deliverMonitorLaneMessage(ctx, laneId, ctx.readStdin());
|
|
8829
|
+
if (!result.ok)
|
|
8830
|
+
throw result.error;
|
|
8831
|
+
if (result.response !== undefined)
|
|
8832
|
+
printJson(result.response);
|
|
8839
8833
|
}));
|
|
8840
8834
|
lanes
|
|
8841
8835
|
.command("resume")
|
package/dist/commands/mesh.js
CHANGED
|
@@ -56,6 +56,7 @@ import { deriveRemoteOwnerSlug, deriveRepoIdentityKey, } from "../lib/work-conte
|
|
|
56
56
|
import { promptRepoCompany, } from "../lib/work-context/repo-prompt.js";
|
|
57
57
|
import { requeueQuarantinedOutbox } from "../lib/work-context/outbox.js";
|
|
58
58
|
import { handOffInstallHere } from "../lib/daemon/handoff.js";
|
|
59
|
+
import { runResidentCommandWithPackageLease } from "../utils/resident-package-preload.js";
|
|
59
60
|
export function formatCheckLines(threads, company, projectId) {
|
|
60
61
|
if (threads.length === 0) {
|
|
61
62
|
return ["Work mesh: no active project threads found."];
|
|
@@ -2108,7 +2109,7 @@ export function registerMeshCommand(program) {
|
|
|
2108
2109
|
.command("run")
|
|
2109
2110
|
.description("Start the single-instance daemon (pid lock, spool watch, presence)")
|
|
2110
2111
|
.option("--hq-root <path>", "HQ tree root (else HQ_ROOT / persisted trusted roots); the Windows task passes this explicitly")
|
|
2111
|
-
.action((opts) => wrap(() => runDaemonRun(opts))());
|
|
2112
|
+
.action((opts) => wrap(() => runResidentCommandWithPackageLease("mesh-daemon", () => runDaemonRun(opts)))());
|
|
2112
2113
|
daemon
|
|
2113
2114
|
.command("install")
|
|
2114
2115
|
.description("Install LaunchAgent (macOS), systemd user unit (Linux), or Scheduled Task (Windows)")
|
|
@@ -3,6 +3,7 @@ import { Command } from "commander";
|
|
|
3
3
|
import { drainDropboxAtPath } from "../lib/lanes/dropbox.js";
|
|
4
4
|
import { recordMonitorTargetActivity, type MonitorMetadata, type MonitorState, type MonitorTarget, type MonitorProcessEntry, type MonitorRuntimeIdentity } from "../lib/monitor.js";
|
|
5
5
|
import type { LaneCompanyRef, LaneProvider } from "../lib/lanes/types.js";
|
|
6
|
+
import { createMonitorLaneMessageApi, type MonitorLaneMessageApi } from "./lanes.js";
|
|
6
7
|
export declare function findSessionOwner(target: MonitorTarget, deps?: {
|
|
7
8
|
env?: NodeJS.ProcessEnv;
|
|
8
9
|
parentPid?: number;
|
|
@@ -21,13 +22,25 @@ export declare function runMonitorEnabledCommand(deps?: {
|
|
|
21
22
|
}): Promise<number>;
|
|
22
23
|
export declare function armText(meta: MonitorMetadata): string;
|
|
23
24
|
export declare function resolveMonitorStartTarget(hqRoot: string, discovered: MonitorTarget, explicitlyProvided: boolean, runtime?: MonitorRuntimeIdentity): MonitorTarget;
|
|
24
|
-
export declare function
|
|
25
|
+
export declare function invokeLaneMonitorMessage(hqRoot: string, meta: MonitorMetadata, sequence: number, text: string, inProcess?: MonitorLaneMessageApi): {
|
|
26
|
+
delivered: boolean;
|
|
27
|
+
outcome: string;
|
|
28
|
+
} | Promise<{
|
|
29
|
+
delivered: boolean;
|
|
30
|
+
outcome: string;
|
|
31
|
+
}>;
|
|
32
|
+
export declare function deliverNormalEvent(hqRoot: string, meta: MonitorMetadata, state: MonitorState, rawText: string, inProcess?: MonitorLaneMessageApi): Promise<MonitorState>;
|
|
25
33
|
export interface RunSupervisorDeps {
|
|
26
34
|
resolveRoot?: () => string;
|
|
27
35
|
monitorEnabled?: typeof monitorEnabled;
|
|
28
36
|
deliver?: typeof deliverNormalEvent;
|
|
29
37
|
spawn?: typeof spawn;
|
|
38
|
+
preloadResidentModules?: () => Promise<void>;
|
|
39
|
+
releasePackageUseLease?: () => void;
|
|
40
|
+
reportPreloadFailure?: (error: unknown) => void;
|
|
41
|
+
createLaneMessageApi?: typeof createMonitorLaneMessageApi;
|
|
30
42
|
}
|
|
43
|
+
export declare function preloadMonitorLaneMessageApi(hqRoot: string, meta: MonitorMetadata, deps?: Pick<RunSupervisorDeps, "preloadResidentModules" | "releasePackageUseLease" | "reportPreloadFailure" | "createLaneMessageApi">): Promise<MonitorLaneMessageApi | undefined>;
|
|
31
44
|
export declare function runSupervisor(id: string, deps?: RunSupervisorDeps): Promise<void>;
|
|
32
45
|
interface MonitorHookResult {
|
|
33
46
|
stdout: string;
|
package/dist/commands/monitor.js
CHANGED
|
@@ -10,6 +10,9 @@ import { appendDropboxMessageAtPath, drainDropboxAtPath, formatDropboxMessages }
|
|
|
10
10
|
import { dispatchLaneDelivery } from "../lib/lanes/delivery-core.js";
|
|
11
11
|
import { MONITOR_FLAG, MONITOR_FLAG_DEFAULT, MONITOR_DEFAULT_CHECKIN_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_POLL_INTERVAL_MS, MONITOR_BATCH_WINDOW_MS, MONITOR_MAX_EVENTS_PER_WINDOW, MONITOR_MAX_FLOOD_WINDOWS, MONITOR_RATE_WINDOW_MS, MONITOR_SCHEMA_VERSION, monitorDir, monitorSessionDir, monitorSessionHasActiveMarkerForOwner, monitorSessionHasActiveMarkers, monitorSessionHasWork, monitorSessionInboxHasEvents, monitorTargetKey, assertMonitorTimeoutCompatibility, parseMonitorDuration, parseMonitorTarget, detectMonitorTarget, findNearestMonitorRuntime, makeMonitorId, recordMonitorTargetDelivery, recordMonitorTargetActivity, recordMonitorTargetDeliveryAtPath, runMonitorCheckinTick, readMonitorPidLiveness, recordHookSessionMapping, resolveMappedSessionId, parseHookSessionId, withMonitorTargetLock, nextMonitorEventSequence, recordMonitorEventState, requestMonitorStop, nextMonitorTimeoutDelay } from "../lib/monitor.js";
|
|
12
12
|
import { readProcStarttime } from "../lib/lanes/spawn.js";
|
|
13
|
+
import { createMonitorLaneMessageApi } from "./lanes.js";
|
|
14
|
+
import { releaseCurrentPackageUseLease, releasePackageUseLeaseAfterResidentPreload } from "../utils/package-use-lease.js";
|
|
15
|
+
import { preloadResidentPackageModules, reportResidentPackagePreloadFailure, runResidentCommandWithPackageLease, } from "../utils/resident-package-preload.js";
|
|
13
16
|
const RUNTIME_ENV = {
|
|
14
17
|
claude: "CLAUDE_CODE_SESSION_ID",
|
|
15
18
|
codex: "CODEX_THREAD_ID",
|
|
@@ -418,7 +421,7 @@ function removeActiveMarker(hqRoot, meta) {
|
|
|
418
421
|
return;
|
|
419
422
|
fs.rmSync(path.join(monitorSessionDir(hqRoot, meta.target.provider, meta.target.sessionId), "active", meta.monitor_id), { force: true });
|
|
420
423
|
}
|
|
421
|
-
async function deliverLaneEvent(hqRoot, meta, sequence, text) {
|
|
424
|
+
async function deliverLaneEvent(hqRoot, meta, sequence, text, inProcess) {
|
|
422
425
|
if (meta.target.kind !== "lane")
|
|
423
426
|
throw new LanesError("monitor_lane_target_required", "Lane delivery requires a lane target.");
|
|
424
427
|
const lane = tryReadLane(hqRoot, meta.target.laneId);
|
|
@@ -427,8 +430,8 @@ async function deliverLaneEvent(hqRoot, meta, sequence, text) {
|
|
|
427
430
|
let dispatched;
|
|
428
431
|
try {
|
|
429
432
|
dispatched = await dispatchLaneDelivery(lane, {
|
|
430
|
-
dropbox: () => invokeLaneMonitorMessage(hqRoot, meta, sequence, text),
|
|
431
|
-
resume: () => invokeLaneMonitorMessage(hqRoot, meta, sequence, text),
|
|
433
|
+
dropbox: () => invokeLaneMonitorMessage(hqRoot, meta, sequence, text, inProcess),
|
|
434
|
+
resume: () => invokeLaneMonitorMessage(hqRoot, meta, sequence, text, inProcess),
|
|
432
435
|
});
|
|
433
436
|
}
|
|
434
437
|
catch (err) {
|
|
@@ -438,9 +441,24 @@ async function deliverLaneEvent(hqRoot, meta, sequence, text) {
|
|
|
438
441
|
}
|
|
439
442
|
return { ...dispatched.value, outcome: `${dispatched.mechanism}:${dispatched.value.outcome}` };
|
|
440
443
|
}
|
|
441
|
-
function invokeLaneMonitorMessage(hqRoot, meta, sequence, text) {
|
|
444
|
+
export function invokeLaneMonitorMessage(hqRoot, meta, sequence, text, inProcess) {
|
|
442
445
|
if (meta.target.kind !== "lane")
|
|
443
446
|
throw new LanesError("monitor_lane_target_required", "Lane delivery requires a lane target.");
|
|
447
|
+
if (inProcess) {
|
|
448
|
+
return inProcess(meta.target.laneId, { text, monitor_id: meta.monitor_id, description: meta.description, sequence })
|
|
449
|
+
.then((result) => {
|
|
450
|
+
if (!result.ok)
|
|
451
|
+
return { delivered: false, outcome: result.errorCode };
|
|
452
|
+
const response = result.response;
|
|
453
|
+
if (response === undefined) {
|
|
454
|
+
throw new LanesError("monitor_lane_delivery_invalid_response", "The lane delivery command returned invalid JSON: Unexpected end of JSON input.", {});
|
|
455
|
+
}
|
|
456
|
+
return {
|
|
457
|
+
delivered: response.accepted === true,
|
|
458
|
+
outcome: String(response.delivery_status ?? response.delivery ?? "accepted"),
|
|
459
|
+
};
|
|
460
|
+
});
|
|
461
|
+
}
|
|
444
462
|
const cliEntrypoint = process.argv[1];
|
|
445
463
|
if (!cliEntrypoint)
|
|
446
464
|
throw new LanesError("monitor_cli_path_missing", "Could not locate the hq CLI entry point for lane delivery.");
|
|
@@ -488,16 +506,16 @@ function deliverSessionEvent(hqRoot, meta, sequence, text) {
|
|
|
488
506
|
});
|
|
489
507
|
return { delivered: true, outcome: "session_inbox" };
|
|
490
508
|
}
|
|
491
|
-
async function deliverTargetEvent(hqRoot, meta, sequence, text) {
|
|
509
|
+
async function deliverTargetEvent(hqRoot, meta, sequence, text, inProcess) {
|
|
492
510
|
return meta.target.kind === "lane"
|
|
493
|
-
? deliverLaneEvent(hqRoot, meta, sequence, text)
|
|
511
|
+
? deliverLaneEvent(hqRoot, meta, sequence, text, inProcess)
|
|
494
512
|
: deliverSessionEvent(hqRoot, meta, sequence, text);
|
|
495
513
|
}
|
|
496
|
-
export async function deliverNormalEvent(hqRoot, meta, state, rawText) {
|
|
514
|
+
export async function deliverNormalEvent(hqRoot, meta, state, rawText, inProcess) {
|
|
497
515
|
return withMonitorTargetLock(hqRoot, meta.target_key, async (activityPath) => {
|
|
498
516
|
const current = readJson(statePath(hqRoot, meta.monitor_id)) ?? state;
|
|
499
517
|
const sequence = nextMonitorEventSequence(current);
|
|
500
|
-
const outcome = await deliverTargetEvent(hqRoot, meta, sequence, rawText);
|
|
518
|
+
const outcome = await deliverTargetEvent(hqRoot, meta, sequence, rawText, inProcess);
|
|
501
519
|
const event = { seq: sequence, at: new Date().toISOString(), text: rawText, delivery: outcome.delivered ? "delivered" : `undeliverable:${outcome.outcome}` };
|
|
502
520
|
const next = appendEventRecord(hqRoot, meta.monitor_id, current, event);
|
|
503
521
|
if (outcome.delivered)
|
|
@@ -512,7 +530,7 @@ function targetEnded(hqRoot, meta) {
|
|
|
512
530
|
const lane = tryReadLane(hqRoot, meta.target.laneId);
|
|
513
531
|
return !lane || ["killed", "cancelled", "failed"].includes(lane.state);
|
|
514
532
|
}
|
|
515
|
-
async function monitorCheckin(hqRoot, meta, state) {
|
|
533
|
+
async function monitorCheckin(hqRoot, meta, state, inProcess) {
|
|
516
534
|
await runMonitorCheckinTick(hqRoot, meta.target_key, {
|
|
517
535
|
now: () => new Date(),
|
|
518
536
|
isWakeable: async (targetKey) => {
|
|
@@ -540,7 +558,7 @@ async function monitorCheckin(hqRoot, meta, state) {
|
|
|
540
558
|
return { delivered: false, outcome: "no_live_monitor" };
|
|
541
559
|
const monitorState = readJson(statePath(hqRoot, monitor.monitor_id)) ?? state;
|
|
542
560
|
const sequence = nextMonitorEventSequence(monitorState);
|
|
543
|
-
const outcome = await deliverTargetEvent(hqRoot, monitor, sequence, text);
|
|
561
|
+
const outcome = await deliverTargetEvent(hqRoot, monitor, sequence, text, inProcess);
|
|
544
562
|
const event = { seq: sequence, at: new Date().toISOString(), text, delivery: outcome.delivered ? "delivered" : `undeliverable:${outcome.outcome}` };
|
|
545
563
|
appendEventRecord(hqRoot, monitor.monitor_id, monitorState, event);
|
|
546
564
|
return outcome;
|
|
@@ -557,6 +575,16 @@ function activeTargetMeta(hqRoot, targetKey) {
|
|
|
557
575
|
return meta?.target_key === targetKey && state?.status === "running" && state.pid !== null && readMonitorPidLiveness(state.pid, state.starttime) ? [meta] : [];
|
|
558
576
|
});
|
|
559
577
|
}
|
|
578
|
+
export async function preloadMonitorLaneMessageApi(hqRoot, meta, deps = {}) {
|
|
579
|
+
if (meta.target.kind !== "lane")
|
|
580
|
+
return undefined;
|
|
581
|
+
let laneMessageApi;
|
|
582
|
+
await releasePackageUseLeaseAfterResidentPreload(async () => {
|
|
583
|
+
await (deps.preloadResidentModules ?? (() => preloadResidentPackageModules("monitor-run")))();
|
|
584
|
+
laneMessageApi = (deps.createLaneMessageApi ?? createMonitorLaneMessageApi)(hqRoot, meta.cwd, process.env);
|
|
585
|
+
}, deps.reportPreloadFailure ?? reportResidentPackagePreloadFailure, deps.releasePackageUseLease ?? releaseCurrentPackageUseLease);
|
|
586
|
+
return laneMessageApi;
|
|
587
|
+
}
|
|
560
588
|
export async function runSupervisor(id, deps = {}) {
|
|
561
589
|
const hqRoot = (deps.resolveRoot ?? resolveLanesHqRoot)();
|
|
562
590
|
const dir = monitorDir(hqRoot, id);
|
|
@@ -569,6 +597,7 @@ export async function runSupervisor(id, deps = {}) {
|
|
|
569
597
|
removeActiveMarker(hqRoot, meta);
|
|
570
598
|
return;
|
|
571
599
|
}
|
|
600
|
+
const laneMessageApi = await preloadMonitorLaneMessageApi(hqRoot, meta, deps);
|
|
572
601
|
let state = { ...stateAtStart, status: "running", pid: process.pid, starttime: readProcStarttime(process.pid), started_at: new Date().toISOString() };
|
|
573
602
|
writeJsonAtomic(statePath(hqRoot, id), state);
|
|
574
603
|
let commandChild = null;
|
|
@@ -587,7 +616,7 @@ export async function runSupervisor(id, deps = {}) {
|
|
|
587
616
|
let suppressed = 0;
|
|
588
617
|
let floodWindows = 0;
|
|
589
618
|
let checkinRunning = false;
|
|
590
|
-
const deliver = deps.deliver ?? deliverNormalEvent;
|
|
619
|
+
const deliver = deps.deliver ?? ((root, metadata, current, text) => deliverNormalEvent(root, metadata, current, text, laneMessageApi));
|
|
591
620
|
const perWindowCap = (() => {
|
|
592
621
|
const candidate = Number.parseInt(process.env.HQ_MONITOR_MAX_EVENTS_PER_WINDOW ?? "", 10);
|
|
593
622
|
return Number.isInteger(candidate) && candidate > 0 ? candidate : MONITOR_MAX_EVENTS_PER_WINDOW;
|
|
@@ -711,7 +740,7 @@ export async function runSupervisor(id, deps = {}) {
|
|
|
711
740
|
}
|
|
712
741
|
if (!checkinRunning) {
|
|
713
742
|
checkinRunning = true;
|
|
714
|
-
void monitorCheckin(hqRoot, meta, state)
|
|
743
|
+
void monitorCheckin(hqRoot, meta, state, laneMessageApi)
|
|
715
744
|
.then((next) => { state = next; })
|
|
716
745
|
.catch((err) => writeStderr(`check-in failed: ${errorPath(err)}\n`))
|
|
717
746
|
.finally(() => { checkinRunning = false; });
|
|
@@ -966,11 +995,11 @@ export function registerMonitorCommand(parent) {
|
|
|
966
995
|
});
|
|
967
996
|
monitor.command("wait", { hidden: true }).requiredOption("--provider <provider>")
|
|
968
997
|
.action(async (options) => {
|
|
969
|
-
const result = await runMonitorHookSafely("wait", async () => {
|
|
998
|
+
const result = await runResidentCommandWithPackageLease("monitor-wait", () => runMonitorHookSafely("wait", async () => {
|
|
970
999
|
if (options.provider !== "claude")
|
|
971
1000
|
throw new LanesError("monitor_wait_provider_unsupported", "Only Claude Stop hooks can wait for session monitor events.", { provider: options.provider });
|
|
972
1001
|
return waitForSession(options.provider);
|
|
973
|
-
});
|
|
1002
|
+
}));
|
|
974
1003
|
if (result.stdout)
|
|
975
1004
|
process.stdout.write(result.stdout);
|
|
976
1005
|
process.exitCode = result.exitCode;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
/** Render a native path with the path spelling used by the bundled Bash scripts. */
|
|
3
|
+
export function shellDisplayPath(value) {
|
|
4
|
+
if (process.platform !== "win32")
|
|
5
|
+
return value;
|
|
6
|
+
const absolute = path.win32.resolve(value);
|
|
7
|
+
const match = /^([A-Za-z]):[\\/](.*)$/.exec(absolute);
|
|
8
|
+
if (!match?.[1] || match[2] === undefined)
|
|
9
|
+
return value;
|
|
10
|
+
return `/${match[1].toLowerCase()}/${match[2].replaceAll("\\", "/")}`;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=shell-display-path.js.map
|