@indigoai-us/hq-cli 5.202.1 → 5.203.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,13 +32,15 @@ import { vaultApiFetch } from "../utils/vault-api.js";
32
32
  import { openMeshTransport } from "../lib/mesh/client.js";
33
33
  import { createLaneMesh, emitLaneDecisionEvents, emitLaneTerminalStateEvent, laneMeshEventIdentity, } from "../lib/lanes/mesh-events.js";
34
34
  import { sessionIdFromEnv } from "../lib/mesh/live/session-identity.js";
35
- import { AccountResolutionError, compareLaneQueueOrder, coveredLaneIds, DEFAULT_ACCOUNT_HOMES, LANE_PROVIDERS, LANE_STATES, PROVIDER_HOME_ENV, QUESTION_STATUSES, SENIOR_KINDS, accountStatus, appendCappedHistory, canonicalizeHome, createLane, createQuestion, decideAdmission, defaultLivenessDeps, defaultSystemdUserDir, defaultThrottleDeps, installDrainHook, installReconcileTimer, providerPathEnv, probeDrainHookRegistration, isLanesError, isLaneVersionConflict, isTerminalLaneState, aliveDirectChildren, assignedChildHireGrants, LANE_HIRE_GRANTS_FLAG, planHireGrantBackfill, withHireGrantAdmission, laneStoryLedgerEnabled, validateProjectStories, buildLaneStatusSnapshot, formatLaneStatusHuman, listAccountStatuses, listLaneIds, listQuestionIds, listSessionLiveness, loadLanesConfig, laneRunsHere, MAX_LANE_DEPTH, MONITOR_ERROR_EXIT_CODE, MONITOR_ENGINES, MONITOR_MAX_TIMEOUT_MS, MONITOR_UNCOVERED_EXIT_CODE, MAX_WATCHED_LANES, monitorReminderText, readLiveMonitorEvidence, resolveMachineIdentity as lookupMachineIdentity, loadLivenessIndex, parseLaneProvider, parseLaneRecord, parseLaneState, parseLivenessState, parseQuestionRecord, parseQuestionStatus, parseSeniorKind, readDaemonPresenceConnected, readLane, retryUpdateLane, syncLaneRecordFromOwner, readQuestion, resolveAccount, resolveLaneWorker, ignoredWorkerProfileFields, loadWorkerProfile, runReconcilePass, wakeAnsweredLaneNow, runLaneWatch, sessionLiveness, tryReadLane, uninstallReconcileTimer, updateLane, updateQuestion, writeLanesConfig, appendDropboxMessage, answerDropboxMessage, deliveryRefusalReason, resumeCommandRefusal, dropboxDir, dropboxInboxPath, laneAcceptsDropboxDelivery, laneAcceptsOperatorMessage, laneDeliveryMechanism, hasActiveAdmissionReservation, hasActivePendingResume, hasRecordedSessionId, hasEarlierEligibleQueuedLane, laneAdmissionCapReason, providerSupportsSessionResume, withLaneAdmissionLock, withLaneHireLocks, laneIdForAnswerDelivery, operatorMessageRefusalReason, raiseLaneQuestion, sha256Text, writeQuestionBody, } from "../lib/lanes/index.js";
35
+ import { AccountResolutionError, compareLaneQueueOrder, coveredLaneIds, DEFAULT_ACCOUNT_HOMES, LANE_PROVIDERS, LANE_STATES, PROVIDER_HOME_ENV, QUESTION_STATUSES, SENIOR_KINDS, accountStatus, appendCappedHistory, canonicalizeHome, createLane, createQuestion, decideAdmission, defaultLivenessDeps, defaultSystemdUserDir, defaultThrottleDeps, installDrainHook, installReconcileTimer, providerPathEnv, probeDrainHookRegistration, isLanesError, isLaneVersionConflict, isTerminalLaneState, aliveDirectChildren, assignedChildHireGrants, LANE_HIRE_GRANTS_FLAG, planHireGrantBackfill, withHireGrantAdmission, laneStoryLedgerEnabled, validateProjectStories, buildLaneStatusSnapshot, formatLaneStatusHuman, listAccountStatuses, listLaneIds, listQuestionIds, listSessionLiveness, loadLanesConfig, laneRunsHere, MAX_LANE_DEPTH, MONITOR_ERROR_EXIT_CODE, MONITOR_ENGINES, MONITOR_MAX_TIMEOUT_MS, MONITOR_UNCOVERED_EXIT_CODE, MAX_WATCHED_LANES, monitorReminderText, readLiveMonitorEvidence, resolveMachineIdentity as lookupMachineIdentity, loadLivenessIndex, parseLaneProvider, parseLaneRecord, parseLaneState, parseLivenessState, parseQuestionRecord, parseQuestionStatus, parseSeniorKind, readDaemonPresenceConnected, readLane, retryUpdateLane, syncLaneRecordFromOwner, readQuestion, resolveAccount, resolveLaneWorker, ignoredWorkerProfileFields, loadWorkerProfile, runReconcilePass, wakeAnsweredLaneNow, runLaneWatch, sessionLiveness, tryReadLane, uninstallReconcileTimer, updateLane, updateQuestion, writeLanesConfig, appendDropboxMessage, answerDropboxMessage, deliveryRefusalReason, resumeCommandRefusal, dropboxDir, dropboxInboxPath, laneAcceptsDropboxDelivery, laneAcceptsOperatorMessage, laneDeliveryMechanism, hasActiveAdmissionReservation, hasActivePendingResume, hasRecordedSessionId, hasEarlierEligibleQueuedLane, laneAdmissionCapReason, providerSupportsSessionResume, providerSessionPortable, sessionNotPortableMessage, withLaneAdmissionLock, withLaneHireLocks, laneIdForAnswerDelivery, operatorMessageRefusalReason, raiseLaneQuestion, sha256Text, writeQuestionBody, } from "../lib/lanes/index.js";
36
36
  import { activeLaneStories, laneStories, laneStory, storyWarning, } from "../lib/lanes/stories.js";
37
37
  import { questionBodyAbsPath } from "../lib/lanes/questions.js";
38
38
  import { compactionAfterUsage, } from "../lib/lanes/compaction.js";
39
39
  import { providerCompactAfterMs } from "../lib/lanes/config.js";
40
40
  import { parseCliEffort, resolveLaneEffort, } from "../lib/lanes/effort.js";
41
41
  import { LanesError } from "../lib/lanes/errors.js";
42
+ import { dispatchLaneDelivery } from "../lib/lanes/delivery-core.js";
43
+ import { formatMonitorEvent } from "../lib/lanes/dropbox.js";
42
44
  import { accountQuotaView, loadQuotaState, quotaBlockFor } from "../lib/lanes/quota.js";
43
45
  import { SESSION_MOVE_REASON } from "../lib/lanes/move-account.js";
44
46
  import { ensureSessionHome } from "../lib/lanes/session-relink.js";
@@ -235,6 +237,7 @@ function resolveDeps(deps = {}) {
235
237
  throttleDeps: deps.throttleDeps ?? defaultThrottleDeps(env),
236
238
  existsSync: deps.existsSync ?? ((p) => fs.existsSync(p)),
237
239
  readFileSync: deps.readFileSync ?? ((p, encoding) => fs.readFileSync(p, encoding)),
240
+ readStdin: deps.readStdin ?? (() => fs.readFileSync(0, "utf8")),
238
241
  homedir: deps.homedir ?? (() => os.homedir()),
239
242
  mesh: deps.mesh ?? createDefaultMesh(),
240
243
  sleep: deps.sleep ?? defaultSleep,
@@ -5021,11 +5024,10 @@ async function prepareAccountMove(ctx, lane, input) {
5021
5024
  account: target,
5022
5025
  });
5023
5026
  }
5024
- if (!providerSupportsSessionResume(lane.provider)) {
5025
- throw new LanesError("provider_session_not_portable", `Provider ${lane.provider} has no session resume, so a lane cannot move between its accounts`, { lane_id: laneId, provider: lane.provider });
5026
- }
5027
- if (lane.provider === "grok") {
5028
- throw new LanesError("provider_session_not_portable", `Provider ${lane.provider} has no session resume, so a lane cannot move between its accounts`, { lane_id: laneId, provider: lane.provider });
5027
+ // The grok comparison repeats PROVIDER_SESSION_PORTABLE so TypeScript narrows
5028
+ // the provider for ensureSessionHome below.
5029
+ if (!providerSessionPortable(lane.provider) || lane.provider === "grok") {
5030
+ throw new LanesError("provider_session_not_portable", sessionNotPortableMessage(lane.provider), { lane_id: laneId, provider: lane.provider });
5029
5031
  }
5030
5032
  if (!hasRecordedSessionId(lane)) {
5031
5033
  throw new LanesError("no_provider_session", `Lane ${laneId} has no recorded provider session id, so there is no session to move`, { lane_id: laneId, provider: lane.provider });
@@ -5310,8 +5312,8 @@ async function runMessage(ctx, laneId, opts) {
5310
5312
  state: lane.state,
5311
5313
  });
5312
5314
  }
5313
- if (opts.account !== undefined && !keepCurrentAccount && !providerSupportsSessionResume(lane.provider)) {
5314
- throw new LanesError("provider_session_not_portable", `Provider ${lane.provider} has no session resume, so a lane cannot move between its accounts`, { lane_id: laneId, provider: lane.provider });
5315
+ if (opts.account !== undefined && !keepCurrentAccount && !providerSessionPortable(lane.provider)) {
5316
+ throw new LanesError("provider_session_not_portable", sessionNotPortableMessage(lane.provider), { lane_id: laneId, provider: lane.provider });
5315
5317
  }
5316
5318
  // One decision point for how a follow-up reaches this lane (delivery.ts).
5317
5319
  // `none` refuses before anything is written: no inbox append, no spawn.
@@ -5359,12 +5361,27 @@ async function runMessage(ctx, laneId, opts) {
5359
5361
  if ((opts.project !== undefined || opts.story !== undefined) && ctx.storyLedgerEnabled()) {
5360
5362
  validateProjectStories(hqRoot, projectId, [storyId], lane.company?.slug);
5361
5363
  }
5364
+ const framedMonitorEvent = opts.monitorEvent === undefined
5365
+ ? undefined
5366
+ : formatMonitorEvent({
5367
+ monitorId: opts.monitorEvent.monitor_id,
5368
+ description: opts.monitorEvent.description,
5369
+ sequence: opts.monitorEvent.sequence,
5370
+ text,
5371
+ });
5372
+ const deliveryText = framedMonitorEvent ?? text;
5362
5373
  const dropboxMessage = {
5363
5374
  at,
5364
5375
  message_id: messageId,
5365
5376
  text,
5366
5377
  project_id: projectId,
5367
5378
  story_id: storyId,
5379
+ ...(opts.monitorEvent === undefined ? {} : {
5380
+ kind: "monitor_event",
5381
+ monitor_id: opts.monitorEvent.monitor_id,
5382
+ description: opts.monitorEvent.description,
5383
+ sequence: opts.monitorEvent.sequence,
5384
+ }),
5368
5385
  };
5369
5386
  let resumed = null;
5370
5387
  let move = null;
@@ -5377,7 +5394,13 @@ async function runMessage(ctx, laneId, opts) {
5377
5394
  cliModel: opts.model?.trim() || undefined,
5378
5395
  ...(resumeProfile !== undefined ? { workerProfile: resumeProfile } : {}),
5379
5396
  ...(resumeEffort !== undefined ? { effort: resumeEffort } : {}),
5380
- pending: { trigger: "message", text, message_id: messageId, compact: opts.compact !== false },
5397
+ pending: {
5398
+ trigger: "message",
5399
+ text: deliveryText,
5400
+ ...(opts.monitorEvent === undefined ? {} : { monitor_event: true }),
5401
+ message_id: messageId,
5402
+ compact: opts.compact !== false,
5403
+ },
5381
5404
  });
5382
5405
  lane = move.lane;
5383
5406
  if (move.queued) {
@@ -5395,7 +5418,8 @@ async function runMessage(ctx, laneId, opts) {
5395
5418
  ...(resumeEffort !== undefined ? { effort: resumeEffort } : {}),
5396
5419
  pending: {
5397
5420
  trigger: "message",
5398
- text,
5421
+ text: deliveryText,
5422
+ ...(opts.monitorEvent === undefined ? {} : { monitor_event: true }),
5399
5423
  message_id: messageId,
5400
5424
  compact: opts.compact !== false,
5401
5425
  },
@@ -5423,81 +5447,94 @@ async function runMessage(ctx, laneId, opts) {
5423
5447
  if (move?.queued) {
5424
5448
  // Parked at the target's cap: reconcile resumes the session there.
5425
5449
  }
5426
- else if (mechanism === "dropbox") {
5427
- // Live (or about-to-be-live) process: the PreToolUse drain delivers it.
5428
- if (!laneAcceptsOperatorMessage(lane)) {
5429
- throw new LanesError("lane_not_accepting_messages", operatorMessageRefusalReason(lane.state), { lane_id: laneId, state: lane.state });
5430
- }
5431
- appendDropboxMessage(hqRoot, laneId, dropboxMessage);
5432
- }
5433
5450
  else {
5434
- // Exited worker with a recorded session: queue the message when capacity
5435
- // is occupied, otherwise start its next turn under the shared admission lock.
5436
- assertLaneRunsHereForAdmission(ctx, lane);
5437
- resumed = await withLaneAdmissionLock(hqRoot, lane.provider, async () => {
5438
- const admission = await assessLaneAdmission(ctx, lane, { queueAt: at });
5439
- if (admission.action === "refuse" && admission.error)
5440
- throw admission.error;
5441
- return withResumeHireAdmission(ctx, lane, () => {
5442
- if (admission.action === "queue") {
5443
- const sessionId = lane.provider_session_id;
5444
- if (!sessionId) {
5445
- throw new LanesError("no_provider_session", `Lane ${laneId} has no provider session id to queue this message resume`, {
5446
- lane_id: laneId,
5447
- provider: lane.provider,
5448
- });
5449
- }
5450
- archiveResumeMessage(hqRoot, laneId, dropboxMessage);
5451
- queuedOnAdmission = true;
5452
- return casUpdateLane(hqRoot, laneId, (current) => {
5453
- if (current.version !== lane.version || current.state !== lane.state) {
5454
- throw new LanesError("lane_admission_conflict", `Lane ${laneId} changed while message admission was checked`, {
5455
- lane_id: laneId,
5456
- prepared_version: lane.version,
5457
- version: current.version,
5458
- state: current.state,
5451
+ const dispatched = await dispatchLaneDelivery(lane, {
5452
+ dropbox: () => {
5453
+ // Live (or about-to-be-live) process: the PreToolUse drain delivers it.
5454
+ if (!laneAcceptsOperatorMessage(lane)) {
5455
+ throw new LanesError("lane_not_accepting_messages", operatorMessageRefusalReason(lane.state), { lane_id: laneId, state: lane.state });
5456
+ }
5457
+ appendDropboxMessage(hqRoot, laneId, dropboxMessage);
5458
+ return null;
5459
+ },
5460
+ resume: async () => {
5461
+ // Exited worker with a recorded session: queue the message when capacity
5462
+ // is occupied, otherwise start its next turn under the shared admission lock.
5463
+ assertLaneRunsHereForAdmission(ctx, lane);
5464
+ return withLaneAdmissionLock(hqRoot, lane.provider, async () => {
5465
+ const admission = await assessLaneAdmission(ctx, lane, { queueAt: at });
5466
+ if (admission.action === "refuse" && admission.error)
5467
+ throw admission.error;
5468
+ return withResumeHireAdmission(ctx, lane, () => {
5469
+ if (admission.action === "queue") {
5470
+ const sessionId = lane.provider_session_id;
5471
+ if (!sessionId) {
5472
+ throw new LanesError("no_provider_session", `Lane ${laneId} has no provider session id to queue this message resume`, {
5473
+ lane_id: laneId,
5474
+ provider: lane.provider,
5475
+ });
5476
+ }
5477
+ archiveResumeMessage(hqRoot, laneId, dropboxMessage);
5478
+ queuedOnAdmission = true;
5479
+ return casUpdateLane(hqRoot, laneId, (current) => {
5480
+ if (current.version !== lane.version || current.state !== lane.state) {
5481
+ throw new LanesError("lane_admission_conflict", `Lane ${laneId} changed while message admission was checked`, {
5482
+ lane_id: laneId,
5483
+ prepared_version: lane.version,
5484
+ version: current.version,
5485
+ state: current.state,
5486
+ });
5487
+ }
5488
+ return {
5489
+ ...current,
5490
+ state: "queued",
5491
+ queued_reason: admission.reason ?? "throttle",
5492
+ queued_at: at,
5493
+ pending_resume: {
5494
+ session_id: sessionId,
5495
+ trigger: "message",
5496
+ text: deliveryText,
5497
+ ...(opts.monitorEvent === undefined ? {} : { monitor_event: true }),
5498
+ message_id: messageId,
5499
+ compact: opts.compact !== false,
5500
+ at,
5501
+ },
5502
+ };
5459
5503
  });
5460
5504
  }
5461
- return {
5462
- ...current,
5463
- state: "queued",
5464
- queued_reason: admission.reason ?? "throttle",
5465
- queued_at: at,
5466
- pending_resume: {
5467
- session_id: sessionId,
5468
- trigger: "message",
5469
- text,
5505
+ const started = spawnLaneWorker(hqRoot, lane, {
5506
+ env: ctx.env,
5507
+ modelDeps: {
5508
+ readFileSync: ctx.readFileSync,
5509
+ probe: ctx.probeProvider,
5510
+ env: ctx.env,
5511
+ },
5512
+ existsSync: ctx.existsSync,
5513
+ spawnProcess: ctx.spawnProcess,
5514
+ proveDetached: ctx.proveDetached,
5515
+ killProcess: ctx.killProcess,
5516
+ now: ctx.now,
5517
+ resolveMachineIdentity: ctx.resolveMachineIdentity,
5518
+ runCompaction: ctx.runCompaction,
5519
+ locateTranscript: ctx.locateTranscript,
5520
+ }, {
5521
+ trigger: {
5522
+ kind: "message",
5523
+ text: deliveryText,
5470
5524
  message_id: messageId,
5471
- compact: opts.compact !== false,
5472
- at,
5525
+ ...(opts.monitorEvent === undefined ? {} : { monitor_event: true }),
5473
5526
  },
5474
- };
5527
+ compact: opts.compact !== false,
5528
+ effort: resumeEffort ?? recordedResumeEffort(lane),
5529
+ });
5530
+ archiveResumeMessage(hqRoot, laneId, dropboxMessage);
5531
+ return started;
5475
5532
  });
5476
- }
5477
- const started = spawnLaneWorker(hqRoot, lane, {
5478
- env: ctx.env,
5479
- modelDeps: {
5480
- readFileSync: ctx.readFileSync,
5481
- probe: ctx.probeProvider,
5482
- env: ctx.env,
5483
- },
5484
- existsSync: ctx.existsSync,
5485
- spawnProcess: ctx.spawnProcess,
5486
- proveDetached: ctx.proveDetached,
5487
- killProcess: ctx.killProcess,
5488
- now: ctx.now,
5489
- resolveMachineIdentity: ctx.resolveMachineIdentity,
5490
- runCompaction: ctx.runCompaction,
5491
- locateTranscript: ctx.locateTranscript,
5492
- }, {
5493
- trigger: { kind: "message", text, message_id: messageId },
5494
- compact: opts.compact !== false,
5495
- effort: resumeEffort ?? recordedResumeEffort(lane),
5496
- });
5497
- archiveResumeMessage(hqRoot, laneId, dropboxMessage);
5498
- return started;
5499
- });
5500
- }, ctx.sleep);
5533
+ }, ctx.sleep);
5534
+ },
5535
+ }, mechanism);
5536
+ if (dispatched.mechanism === "resume")
5537
+ resumed = dispatched.value;
5501
5538
  }
5502
5539
  // Every accepted message moves the compaction reference forward.
5503
5540
  let next = casUpdateLane(hqRoot, laneId, (current) => ({
@@ -5736,8 +5773,6 @@ async function runClaudeBalanceMoveTarget(ctx, laneId, opts) {
5736
5773
  });
5737
5774
  }
5738
5775
  function laneWithRecoveredProviderSession(hqRoot, lane) {
5739
- if (lane.provider === "grok")
5740
- return lane;
5741
5776
  const manifest = readSpawnManifest(laneRunDir(hqRoot, lane.lane_id));
5742
5777
  const sessionId = (typeof lane.provider_session_id === "string" && lane.provider_session_id.trim()
5743
5778
  ? lane.provider_session_id
@@ -5795,8 +5830,8 @@ async function runResume(ctx, laneId, opts) {
5795
5830
  state: lane.state,
5796
5831
  });
5797
5832
  }
5798
- if (opts.account !== undefined && !providerSupportsSessionResume(lane.provider)) {
5799
- throw new LanesError("provider_session_not_portable", `Provider ${lane.provider} has no session resume, so a lane cannot move between its accounts`, { lane_id: laneId, provider: lane.provider });
5833
+ if (opts.account !== undefined && !providerSessionPortable(lane.provider)) {
5834
+ throw new LanesError("provider_session_not_portable", sessionNotPortableMessage(lane.provider), { lane_id: laneId, provider: lane.provider });
5800
5835
  }
5801
5836
  if (lane.state === "queued") {
5802
5837
  throw new LanesError("lane_not_resumable", `Lane ${laneId} is queued; use hq lanes admit ${laneId} to request admission`, { lane_id: laneId, state: lane.state, admission_command: `hq lanes admit ${laneId}` });
@@ -8304,6 +8339,38 @@ export function registerLanesCommand(parent, deps = {}) {
8304
8339
  .action(wrap(async (laneId, opts) => {
8305
8340
  await runMessage(ctx, laneId, opts);
8306
8341
  }));
8342
+ lanes
8343
+ .command("_monitor-message", { hidden: true })
8344
+ .argument("<lane-id>", "Lane id")
8345
+ .action(wrap(async (laneId) => {
8346
+ const input = ctx.readStdin();
8347
+ let payload;
8348
+ try {
8349
+ payload = JSON.parse(input);
8350
+ }
8351
+ catch (err) {
8352
+ throw new LanesError("monitor_lane_payload_invalid", `Monitor lane delivery payload is invalid JSON: ${err instanceof Error ? err.message : String(err)}.`, {});
8353
+ }
8354
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
8355
+ throw new LanesError("monitor_lane_payload_invalid", "Monitor lane delivery payload must be an object.", {});
8356
+ }
8357
+ const value = payload;
8358
+ if (typeof value.text !== "string" ||
8359
+ typeof value.monitor_id !== "string" ||
8360
+ typeof value.description !== "string" ||
8361
+ !Number.isInteger(value.sequence) ||
8362
+ Number(value.sequence) < 1) {
8363
+ throw new LanesError("monitor_lane_payload_invalid", "Monitor lane delivery payload is missing text, monitor metadata, or sequence.", {});
8364
+ }
8365
+ await runMessage(ctx, laneId, {
8366
+ text: value.text,
8367
+ monitorEvent: {
8368
+ monitor_id: value.monitor_id,
8369
+ description: value.description,
8370
+ sequence: Number(value.sequence),
8371
+ },
8372
+ });
8373
+ }));
8307
8374
  lanes
8308
8375
  .command("resume")
8309
8376
  .description("Resume an interrupted, done or blocked lane on its recorded provider session")
@@ -0,0 +1,58 @@
1
+ import { spawn } from "node:child_process";
2
+ import { Command } from "commander";
3
+ import { drainDropboxAtPath } from "../lib/lanes/dropbox.js";
4
+ import { recordMonitorTargetActivity, type MonitorMetadata, type MonitorState, type MonitorTarget, type MonitorProcessEntry, type MonitorRuntimeIdentity } from "../lib/monitor.js";
5
+ import type { LaneCompanyRef, LaneProvider } from "../lib/lanes/types.js";
6
+ export declare function findSessionOwner(target: MonitorTarget, deps?: {
7
+ env?: NodeJS.ProcessEnv;
8
+ parentPid?: number;
9
+ readProcess?: (pid: number) => MonitorProcessEntry | null;
10
+ readStarttime?: (pid: number) => number | null;
11
+ }): {
12
+ pid: number;
13
+ starttime: number | null;
14
+ } | null;
15
+ export declare function sessionOwnerTarget(discovered: MonitorTarget, resolved: MonitorTarget): MonitorTarget;
16
+ declare function monitorEnabled(company?: LaneCompanyRef | null): Promise<boolean>;
17
+ export declare function runMonitorEnabledCommand(deps?: {
18
+ readFlag?: (company: LaneCompanyRef | null) => Promise<boolean>;
19
+ writeOut?: (text: string) => void;
20
+ writeError?: (text: string) => void;
21
+ }): Promise<number>;
22
+ export declare function armText(meta: MonitorMetadata): string;
23
+ export declare function resolveMonitorStartTarget(hqRoot: string, discovered: MonitorTarget, explicitlyProvided: boolean, runtime?: MonitorRuntimeIdentity): MonitorTarget;
24
+ export declare function deliverNormalEvent(hqRoot: string, meta: MonitorMetadata, state: MonitorState, rawText: string): Promise<MonitorState>;
25
+ export interface RunSupervisorDeps {
26
+ resolveRoot?: () => string;
27
+ monitorEnabled?: typeof monitorEnabled;
28
+ deliver?: typeof deliverNormalEvent;
29
+ spawn?: typeof spawn;
30
+ }
31
+ export declare function runSupervisor(id: string, deps?: RunSupervisorDeps): Promise<void>;
32
+ interface MonitorHookResult {
33
+ stdout: string;
34
+ exitCode: 0 | 2;
35
+ }
36
+ export interface WaitForSessionDeps {
37
+ monitorEnabled?: () => Promise<boolean>;
38
+ resolveRoot?: () => string;
39
+ readStdin?: () => Promise<string>;
40
+ recordActivity?: typeof recordMonitorTargetActivity;
41
+ drainDropbox?: typeof drainDropboxAtPath;
42
+ sleep?: (milliseconds: number) => Promise<void>;
43
+ }
44
+ export declare function runMonitorHookSafely(kind: "drain" | "wait", operation: () => Promise<MonitorHookResult>, writeError?: (text: string) => void): Promise<MonitorHookResult>;
45
+ export interface DrainSessionDeps {
46
+ monitorEnabled?: () => Promise<boolean>;
47
+ resolveRoot?: () => string;
48
+ readStdin?: () => Promise<string>;
49
+ sessionEnvironmentId?: (provider: LaneProvider) => string | undefined;
50
+ nearestRuntimeIdentity?: () => MonitorRuntimeIdentity | undefined;
51
+ recordActivity?: typeof recordMonitorTargetActivity;
52
+ drainDropbox?: typeof drainDropboxAtPath;
53
+ }
54
+ export declare function drainSession(provider: LaneProvider, event: "PreToolUse" | "UserPromptSubmit", deps?: DrainSessionDeps): Promise<MonitorHookResult>;
55
+ export declare function waitForSession(provider: LaneProvider, deps?: WaitForSessionDeps): Promise<MonitorHookResult>;
56
+ export declare function registerMonitorCommand(parent: Command): Command;
57
+ export {};
58
+ //# sourceMappingURL=monitor.d.ts.map