@indigoai-us/hq-cli 5.345.62 → 5.345.64
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 +8 -0
- package/dist/command-catalog.generated.d.ts +736 -0
- package/dist/command-catalog.generated.js +907 -0
- package/dist/commands/lanes-link.d.ts +3 -0
- package/dist/commands/lanes-link.js +83 -0
- package/dist/commands/lanes-loop.js +5 -6
- package/dist/commands/lanes-questions.js +27 -3
- package/dist/commands/lanes.js +26 -4
- package/dist/lib/daemon/catalog.d.ts +5 -0
- package/dist/lib/daemon/catalog.js +3 -0
- package/dist/lib/daemon/run.d.ts +6 -0
- package/dist/lib/daemon/run.js +13 -1
- package/dist/lib/lanes/links.d.ts +39 -0
- package/dist/lib/lanes/links.js +450 -0
- package/dist/lib/lanes/loop.d.ts +7 -2
- package/dist/lib/lanes/loop.js +169 -57
- package/dist/lib/mesh/live/flush.d.ts +7 -1
- package/dist/lib/mesh/live/flush.js +15 -7
- package/dist/lib/mesh/live/format-spool-line.d.ts +3 -1
- package/dist/lib/mesh/live/format-spool-line.js +3 -0
- package/dist/lib/mesh/live/index.d.ts +2 -0
- package/dist/lib/mesh/live/index.js +1 -0
- package/dist/lib/mesh/live/session-event.schema.json +9 -2
- package/dist/lib/mesh/live/validate-session-event.d.ts +1 -1
- package/dist/lib/mesh/live/validate-session-event.js +1 -1
- package/dist/lib/mesh/live/work-location.d.ts +30 -0
- package/dist/lib/mesh/live/work-location.js +86 -0
- package/dist/utils/version-gate.js +5 -1
- package/package.json +1 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { resolveLanesHqRoot } from "../lib/lanes/hq-root.js";
|
|
2
|
+
import { readLanesRegistryFlagFailOpen } from "../lib/lanes/registry-flag.js";
|
|
3
|
+
import { isLinkedSession, linkedSessionIdFromHookInput, LANE_SESSION_LINKS_FLAG, LaneLinkError, runLaneLinkWithFlag } from "../lib/lanes/links.js";
|
|
4
|
+
function writeJson(value) {
|
|
5
|
+
process.stdout.write(`${JSON.stringify(value)}\n`);
|
|
6
|
+
}
|
|
7
|
+
function addLinkOptions(command) {
|
|
8
|
+
return command
|
|
9
|
+
.option("--json", "Print JSON output (the default)")
|
|
10
|
+
.option("--session-id <id>", "Act as this session")
|
|
11
|
+
.option("--link <id>", "Conduct link id")
|
|
12
|
+
.option("--child <name|all>", "Child name or all children")
|
|
13
|
+
.option("--name <name>", "Child name")
|
|
14
|
+
.option("--engine <engine>", "Session engine")
|
|
15
|
+
.option("--title <title>", "Session title")
|
|
16
|
+
.option("--host-session <id>", "Host session id")
|
|
17
|
+
.option("--text <message>", "Message text")
|
|
18
|
+
.option("--text-file <path>", "Read message text from a file")
|
|
19
|
+
.option("--state <state>", "Child state")
|
|
20
|
+
.option("--note <note>", "State note")
|
|
21
|
+
.option("--timeout <seconds>", "Wait timeout in seconds", (value) => Number(value));
|
|
22
|
+
}
|
|
23
|
+
async function readHookInput() {
|
|
24
|
+
const chunks = [];
|
|
25
|
+
for await (const chunk of process.stdin)
|
|
26
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
27
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
28
|
+
}
|
|
29
|
+
function commandError(error) {
|
|
30
|
+
const code = error instanceof LaneLinkError ? error.code : "internal";
|
|
31
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
32
|
+
process.stderr.write(`hq lanes link: ${message}\n`);
|
|
33
|
+
writeJson({ error: code, message });
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
}
|
|
36
|
+
export function registerLanesLinkCommand(lanes) {
|
|
37
|
+
const link = lanes.command("link").description("Link live sessions to a conductor through session inboxes");
|
|
38
|
+
const commands = ["open", "join", "send", "report", "status", "inbox", "read", "wait", "list", "leave", "close"];
|
|
39
|
+
for (const subcommand of commands) {
|
|
40
|
+
addLinkOptions(link.command(subcommand)).action(async (options) => {
|
|
41
|
+
try {
|
|
42
|
+
const root = resolveLanesHqRoot(process.env);
|
|
43
|
+
const enabled = await readLanesRegistryFlagFailOpen(LANE_SESSION_LINKS_FLAG, {
|
|
44
|
+
env: process.env,
|
|
45
|
+
defaultValue: true,
|
|
46
|
+
});
|
|
47
|
+
const result = await runLaneLinkWithFlag(subcommand, { ...options, hqRoot: root, env: process.env }, enabled);
|
|
48
|
+
writeJson(result.output ?? {});
|
|
49
|
+
if (result.exitCode !== undefined)
|
|
50
|
+
process.exitCode = result.exitCode;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
commandError(error);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const deliver = link.command("_deliver", { hidden: true })
|
|
58
|
+
.description("Internal linked-session hook delivery")
|
|
59
|
+
.requiredOption("--event <event>", "Hook event");
|
|
60
|
+
deliver.action(async (options) => {
|
|
61
|
+
// Hook commands must not update/re-exec the CLI inside the provider's time budget.
|
|
62
|
+
process.env.HQ_NO_UPDATE_CHECK = "1";
|
|
63
|
+
try {
|
|
64
|
+
const root = resolveLanesHqRoot(process.env);
|
|
65
|
+
const input = await readHookInput();
|
|
66
|
+
const sid = linkedSessionIdFromHookInput(input);
|
|
67
|
+
if (!sid || !isLinkedSession(root, sid))
|
|
68
|
+
return;
|
|
69
|
+
const enabled = await readLanesRegistryFlagFailOpen(LANE_SESSION_LINKS_FLAG, {
|
|
70
|
+
env: process.env,
|
|
71
|
+
defaultValue: true,
|
|
72
|
+
});
|
|
73
|
+
const result = await runLaneLinkWithFlag("_deliver", { hqRoot: root, env: process.env, event: options.event, input }, enabled);
|
|
74
|
+
if (result.output)
|
|
75
|
+
writeJson(result.output);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
process.stderr.write(`hq lanes link _deliver: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
79
|
+
// Hook failures are fail-open; queued messages remain available if delivery failed.
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=lanes-link.js.map
|
|
@@ -17,12 +17,11 @@ export function startLaneLoopController(ctx, laneId, initialAdmission = false) {
|
|
|
17
17
|
const entry = process.argv[1];
|
|
18
18
|
if (!entry)
|
|
19
19
|
throw new LanesError("loop_controller_entry_missing", "Cannot resolve the hq CLI entry point for the loop controller", { lane_id: laneId });
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
stdio: "ignore",
|
|
24
|
-
|
|
25
|
-
});
|
|
20
|
+
const args = [entry, "lanes", "_loop-worker", laneId];
|
|
21
|
+
const env = { ...ctx.env, HQ_LANE_LOOP_CONTROLLER: "1", ...(initialAdmission ? { HQ_LANE_LOOP_INITIAL: "1" } : {}) };
|
|
22
|
+
const child = ctx.spawnProcess
|
|
23
|
+
? ctx.spawnProcess(process.execPath, args, { cwd: ctx.hqRoot(), detached: true, windowsHide: true, stdio: ["ignore", 1, 2], env })
|
|
24
|
+
: spawn(process.execPath, args, { cwd: ctx.hqRoot(), detached: true, stdio: "ignore", env });
|
|
26
25
|
child.unref();
|
|
27
26
|
if (child.pid === undefined)
|
|
28
27
|
throw new LanesError("loop_controller_spawn_failed", "Loop controller did not start", { lane_id: laneId });
|
|
@@ -5,7 +5,7 @@ import { sessionIdFromEnv } from "../lib/mesh/live/session-identity.js";
|
|
|
5
5
|
import { appendCappedHistory, createQuestion, isLanesError, listSessionLiveness, parseLivenessState, parseQuestionRecord, parseQuestionStatus, readDaemonPresenceConnected, readLane, readQuestion, wakeAnsweredLaneNow, sessionLiveness, appendDropboxMessage, answerDropboxMessage, laneAcceptsDropboxDelivery, laneIdForAnswerDelivery, writeQuestionBody } from "../lib/lanes/index.js";
|
|
6
6
|
import { resolveQuestionCompanyWithFallback } from "../lib/lanes/questions.js";
|
|
7
7
|
import { LanesError } from "../lib/lanes/errors.js";
|
|
8
|
-
import { applyLoopStallAnswer } from "../lib/lanes/loop.js";
|
|
8
|
+
import { applyLoopStallAnswer, findLoopStallResult } from "../lib/lanes/loop.js";
|
|
9
9
|
export function resolveAnswerChoice(choice, options, freeform) {
|
|
10
10
|
const trimmed = choice.trim();
|
|
11
11
|
if (/^[0-9]+$/.test(trimmed)) {
|
|
@@ -801,7 +801,6 @@ export function createLaneQuestionsHandlers(deps) {
|
|
|
801
801
|
});
|
|
802
802
|
return;
|
|
803
803
|
}
|
|
804
|
-
throwIfQuestionNotPending(question);
|
|
805
804
|
if (askingLane.state === "awaiting_input") {
|
|
806
805
|
assertLaneRunsHereForOperatorMutation(ctx, askingLane, "wake after answering");
|
|
807
806
|
}
|
|
@@ -819,11 +818,27 @@ export function createLaneQuestionsHandlers(deps) {
|
|
|
819
818
|
throw new LanesError("missing_choice", "--choice or --freeform is required", {});
|
|
820
819
|
}
|
|
821
820
|
const choice = freeform ?? resolveAnswerChoice(opts.choice, body.options, false);
|
|
821
|
+
const isLoopStallQuestion = body.loop_stall?.lane_id === askingLane.lane_id && askingLane.loop_mode === true;
|
|
822
|
+
const incomingAnswerKind = freeform ? "freeform" : "option";
|
|
823
|
+
const incomingNotesMatch = opts.notes
|
|
824
|
+
? question.answer?.notes_ref !== undefined && body.notes === opts.notes
|
|
825
|
+
: question.answer?.notes_ref === undefined;
|
|
826
|
+
const retryingSameLoopAnswer = isLoopStallQuestion && question.status === "answered" && question.answer?.choice === choice &&
|
|
827
|
+
question.answer.answer_kind === incomingAnswerKind && incomingNotesMatch &&
|
|
828
|
+
deps.sameQuestionAnswer(question.answer, { ...question.answer });
|
|
829
|
+
if (question.status !== "pending" && !retryingSameLoopAnswer)
|
|
830
|
+
throwIfQuestionNotPending(question);
|
|
831
|
+
const loopStallResult = isLoopStallQuestion
|
|
832
|
+
? findLoopStallResult(path.join(hqRoot, "workspace", "lanes-runs", askingLane.lane_id), questionId)
|
|
833
|
+
: undefined;
|
|
822
834
|
const at = ctx.now().toISOString();
|
|
823
835
|
const answeredBy = sessionIdFromEnv(ctx.env)
|
|
824
836
|
? `session:${sessionIdFromEnv(ctx.env)}`
|
|
825
837
|
: "user";
|
|
826
838
|
const updated = casUpdateQuestion(hqRoot, questionId, (current) => {
|
|
839
|
+
if (retryingSameLoopAnswer && current.status === "answered" && current.answer?.choice === choice &&
|
|
840
|
+
deps.sameQuestionAnswer(current.answer, question.answer))
|
|
841
|
+
return current;
|
|
827
842
|
throwIfQuestionNotPending(current);
|
|
828
843
|
assertQuestionCompanyAccess(current, askingLane, requestedCompany, hqRoot);
|
|
829
844
|
const recordedCompany = current.company ?? questionCompany;
|
|
@@ -856,7 +871,12 @@ export function createLaneQuestionsHandlers(deps) {
|
|
|
856
871
|
},
|
|
857
872
|
};
|
|
858
873
|
});
|
|
859
|
-
if (
|
|
874
|
+
if (isLoopStallQuestion) {
|
|
875
|
+
if (!loopStallResult && !retryingSameLoopAnswer) {
|
|
876
|
+
process.stderr.write(`hq lanes: loop phase for question ${questionId} was already re-enqueued; recording answer as superseded\n`);
|
|
877
|
+
printJson({ ok: true, action: "questions.answer", lane_id: askingLane.lane_id, question: updated, loop_action: "superseded" });
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
860
880
|
const resolved = applyLoopStallAnswer({
|
|
861
881
|
runDir: path.join(hqRoot, "workspace", "lanes-runs", askingLane.lane_id),
|
|
862
882
|
questionId,
|
|
@@ -866,6 +886,10 @@ export function createLaneQuestionsHandlers(deps) {
|
|
|
866
886
|
});
|
|
867
887
|
if (!resolved)
|
|
868
888
|
throw new LanesError("loop_stall_result_missing", `Loop stall result for question ${questionId} is missing`, { question_id: questionId, lane_id: askingLane.lane_id });
|
|
889
|
+
if (resolved.action === "already_applied") {
|
|
890
|
+
printJson({ ok: true, action: "questions.answer", lane_id: askingLane.lane_id, question: updated, loop_action: resolved.action });
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
869
893
|
const controllerPid = await deps.restartLoopController(ctx, askingLane.lane_id);
|
|
870
894
|
printJson({ ok: true, action: "questions.answer", lane_id: askingLane.lane_id, question: updated, loop_action: resolved.action, controller_pid: controllerPid });
|
|
871
895
|
return;
|
package/dist/commands/lanes.js
CHANGED
|
@@ -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 { registerLaneSessionStartCommand } from "./lanes-session-start.js";
|
|
37
|
+
import { registerLanesLinkCommand } from "./lanes-link.js";
|
|
37
38
|
import { laneDepthCap } from "../lib/lanes/depth-cap.js";
|
|
38
39
|
import { isSsmRunCommandProcess } from "../lib/lanes/ssm-command-context.js";
|
|
39
40
|
import { runResidentCommandWithPackageLease } from "../utils/resident-package-preload.js";
|
|
@@ -9431,10 +9432,30 @@ export function registerLanesCommand(parent, deps = {}) {
|
|
|
9431
9432
|
}
|
|
9432
9433
|
const runDirPath = runDir(handlerCtx.hqRoot(), laneId);
|
|
9433
9434
|
if (loopControllerIsAlive(runDirPath)) {
|
|
9434
|
-
|
|
9435
|
-
if (
|
|
9436
|
-
|
|
9437
|
-
|
|
9435
|
+
let status = loopStatus(runDirPath, laneId);
|
|
9436
|
+
if (status.state === "parked") {
|
|
9437
|
+
const deadline = Date.now() + 10_000;
|
|
9438
|
+
while (Date.now() < deadline) {
|
|
9439
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
9440
|
+
status = loopStatus(runDirPath, laneId);
|
|
9441
|
+
if (status.state !== "parked") {
|
|
9442
|
+
if (status.pid === undefined)
|
|
9443
|
+
throw new LanesError("loop_controller_pid_missing", `Loop controller for ${laneId} left parked without a recorded pid`, { lane_id: laneId });
|
|
9444
|
+
return status.pid;
|
|
9445
|
+
}
|
|
9446
|
+
if (!loopControllerIsAlive(runDirPath))
|
|
9447
|
+
break;
|
|
9448
|
+
}
|
|
9449
|
+
if (loopControllerIsAlive(runDirPath) && loopStatus(runDirPath, laneId).state === "parked") {
|
|
9450
|
+
throw new LanesError("loop_controller_winding_down", `Loop controller for ${laneId} stayed parked while winding down`, { lane_id: laneId });
|
|
9451
|
+
}
|
|
9452
|
+
}
|
|
9453
|
+
else {
|
|
9454
|
+
const pid = status.pid;
|
|
9455
|
+
if (pid === undefined)
|
|
9456
|
+
throw new LanesError("loop_controller_pid_missing", `Loop controller for ${laneId} is alive without a recorded pid`, { lane_id: laneId });
|
|
9457
|
+
return pid;
|
|
9458
|
+
}
|
|
9438
9459
|
}
|
|
9439
9460
|
return startLaneLoopController(handlerCtx, laneId);
|
|
9440
9461
|
},
|
|
@@ -9534,6 +9555,7 @@ export function registerLanesCommand(parent, deps = {}) {
|
|
|
9534
9555
|
.command("lanes")
|
|
9535
9556
|
.description("Create, supervise, and steer worker lanes; routed decision queue");
|
|
9536
9557
|
registerLaneSessionStartCommand(lanes);
|
|
9558
|
+
registerLanesLinkCommand(lanes);
|
|
9537
9559
|
registerLaneChecksCommand(lanes, {
|
|
9538
9560
|
hqRoot: ctx.hqRoot,
|
|
9539
9561
|
resolveCompany: ctx.resolveCompany,
|
|
@@ -55,6 +55,11 @@ export interface UnitPlan {
|
|
|
55
55
|
initialDelaySec?: number;
|
|
56
56
|
/** Kill and restart this child after silence on its liveness stream. */
|
|
57
57
|
heartbeatTimeoutMs?: number;
|
|
58
|
+
/**
|
|
59
|
+
* Run the unit and its children at macOS background QoS (`taskpolicy -b`):
|
|
60
|
+
* efficiency cores and throttled disk I/O. For bulk work no user waits on.
|
|
61
|
+
*/
|
|
62
|
+
backgroundQos?: true;
|
|
58
63
|
command: UnitCommand | null;
|
|
59
64
|
env: Record<string, string>;
|
|
60
65
|
blocked?: UnitBlock;
|
|
@@ -252,6 +252,9 @@ function planService(service, ctx) {
|
|
|
252
252
|
intervalSec: 900,
|
|
253
253
|
initialDelaySec: 120,
|
|
254
254
|
command: { type: "hq", args: ["index", "sync", "--hq-root", ctx.hqRoot ?? ""] },
|
|
255
|
+
// A full qmd pass rereads every indexed file; at default priority it
|
|
256
|
+
// got HQ listed under macOS "Using Significant Energy".
|
|
257
|
+
backgroundQos: true,
|
|
255
258
|
blocked: firstBlock([[!ctx.hqRoot, NO_HQ_ROOT]]),
|
|
256
259
|
}),
|
|
257
260
|
];
|
package/dist/lib/daemon/run.d.ts
CHANGED
|
@@ -80,6 +80,12 @@ export declare function syncRunnerSourceForPlan(stagedRunnerPath: string | null,
|
|
|
80
80
|
}, currentSyncRunnerSource?: SyncRunnerSource | null): SyncRunnerSource;
|
|
81
81
|
/** Whether every executable in the first service plan remains usable after the CLI package is replaced. */
|
|
82
82
|
export declare function daemonPlanCanReleasePackageUseLease(plans: readonly UnitPlan[], replaceablePackageRoots: readonly string[], stagingFailed: boolean, hqBootstrapReady?: boolean): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Prefix a unit's command with `taskpolicy -b` on macOS. taskpolicy execs the
|
|
85
|
+
* command in place, so the pid the supervisor tracks is the unit itself, and
|
|
86
|
+
* PRIO_DARWIN_BG is inherited by everything the unit spawns (qmd included).
|
|
87
|
+
*/
|
|
88
|
+
export declare function backgroundQosCommand(command: [string, string[]], backgroundQos: boolean, platform?: NodeJS.Platform | string, exists?: (file: string) => boolean): [string, string[]];
|
|
83
89
|
export declare function daemonHqChildCommand(nodeBinary: string, hqBinary: string, args: readonly string[], bootstrapPath: string | null, packagePrefix: string | null): [string, string[]];
|
|
84
90
|
export declare function resolveSyncRunnerPath(): string | null;
|
|
85
91
|
/** The hosted desktop app uses this env value when planning daemon services. */
|
package/dist/lib/daemon/run.js
CHANGED
|
@@ -203,6 +203,17 @@ export function daemonPlanCanReleasePackageUseLease(plans, replaceablePackageRoo
|
|
|
203
203
|
return executablePaths.every((candidate) => replaceablePackageRoots.every((root) => !isPathWithin(root, candidate)));
|
|
204
204
|
});
|
|
205
205
|
}
|
|
206
|
+
const DARWIN_TASKPOLICY = "/usr/sbin/taskpolicy";
|
|
207
|
+
/**
|
|
208
|
+
* Prefix a unit's command with `taskpolicy -b` on macOS. taskpolicy execs the
|
|
209
|
+
* command in place, so the pid the supervisor tracks is the unit itself, and
|
|
210
|
+
* PRIO_DARWIN_BG is inherited by everything the unit spawns (qmd included).
|
|
211
|
+
*/
|
|
212
|
+
export function backgroundQosCommand(command, backgroundQos, platform = process.platform, exists = fs.existsSync) {
|
|
213
|
+
if (!backgroundQos || platform !== "darwin" || !exists(DARWIN_TASKPOLICY))
|
|
214
|
+
return command;
|
|
215
|
+
return [DARWIN_TASKPOLICY, ["-b", command[0], ...command[1]]];
|
|
216
|
+
}
|
|
206
217
|
export function daemonHqChildCommand(nodeBinary, hqBinary, args, bootstrapPath, packagePrefix) {
|
|
207
218
|
return bootstrapPath && packagePrefix
|
|
208
219
|
? [nodeBinary, [bootstrapPath, packagePrefix, CLI_VERSION, ...args]]
|
|
@@ -751,11 +762,12 @@ export async function runDaemon(opts) {
|
|
|
751
762
|
const command = unit.command;
|
|
752
763
|
if (!command || command.type === "internal")
|
|
753
764
|
throw new Error(`${unit.id} has no process to start`);
|
|
754
|
-
|
|
765
|
+
let [file, args] = command.type === "hq"
|
|
755
766
|
? daemonHqChildCommand(opts.nodeBinary, opts.hqBinary, command.args, stagedHqChildBootstrap?.bootstrapPath ?? null, cliPackagePrefix)
|
|
756
767
|
: command.type === "node"
|
|
757
768
|
? [opts.nodeBinary, [command.script, ...command.args]]
|
|
758
769
|
: [command.file, command.args];
|
|
770
|
+
[file, args] = backgroundQosCommand([file, args], unit.backgroundQos === true);
|
|
759
771
|
const logPath = paths.unitLogPath(unit.id);
|
|
760
772
|
const cwd = unit.env.HQ_ROOT && fs.existsSync(unit.env.HQ_ROOT) ? unit.env.HQ_ROOT : home;
|
|
761
773
|
if (unit.heartbeatTimeoutMs && succession) {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare const LANE_SESSION_LINKS_FLAG = "lanes.session-links";
|
|
2
|
+
export declare class LaneLinkError extends Error {
|
|
3
|
+
readonly code: string;
|
|
4
|
+
constructor(code: string, message: string);
|
|
5
|
+
}
|
|
6
|
+
export interface LinkOptions {
|
|
7
|
+
hqRoot: string;
|
|
8
|
+
sessionId?: string;
|
|
9
|
+
env?: NodeJS.ProcessEnv;
|
|
10
|
+
link?: string;
|
|
11
|
+
child?: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
engine?: string;
|
|
14
|
+
title?: string;
|
|
15
|
+
hostSession?: string;
|
|
16
|
+
text?: string;
|
|
17
|
+
textFile?: string;
|
|
18
|
+
state?: string;
|
|
19
|
+
note?: string;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
event?: string;
|
|
22
|
+
input?: string;
|
|
23
|
+
now?: () => Date;
|
|
24
|
+
sleep?: (milliseconds: number) => Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export interface LinkResult {
|
|
27
|
+
output?: Record<string, unknown>;
|
|
28
|
+
exitCode?: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function resolveLinkSessionId(root: string, explicit: string | undefined, env?: NodeJS.ProcessEnv): string;
|
|
31
|
+
/** Cheap hook guard used before remote flag lookup or queue access. */
|
|
32
|
+
export declare function linkedSessionIdFromHookInput(input: string): string;
|
|
33
|
+
export declare function isLinkedSession(root: string, sid: string): boolean;
|
|
34
|
+
/** Claims pending files by renaming the whole queue, matching conduct-inbox's no-loss drain. */
|
|
35
|
+
export declare function drainLinkQueue(inbox: string): string;
|
|
36
|
+
export declare function runLaneLink(subcommand: string, options: LinkOptions): Promise<LinkResult>;
|
|
37
|
+
/** Apply the default-on feature gate contract at the command boundary. */
|
|
38
|
+
export declare function runLaneLinkWithFlag(subcommand: string, options: LinkOptions, enabled: boolean): Promise<LinkResult>;
|
|
39
|
+
//# sourceMappingURL=links.d.ts.map
|