@indigoai-us/hq-cli 5.345.127 → 5.345.129
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 +47 -0
- package/assets/scaffold/core/scripts/handoff-knowledge-commit.sh +123 -0
- package/assets/scaffold/core/scripts/hq-detach.sh +169 -0
- package/dist/command-catalog.generated.d.ts +40 -2
- package/dist/command-catalog.generated.js +48 -2
- package/dist/commands/auth.js +19 -2
- package/dist/commands/core-bucket-c-handoff-knowledge-fast.d.ts +2 -0
- package/dist/commands/core-bucket-c-handoff-knowledge-fast.js +10 -0
- package/dist/commands/core-bucket-c-handoff-knowledge-native.d.ts +46 -0
- package/dist/commands/core-bucket-c-handoff-knowledge-native.js +284 -0
- package/dist/commands/core-bucket-c-hq-detach-fast.d.ts +2 -0
- package/dist/commands/core-bucket-c-hq-detach-fast.js +10 -0
- package/dist/commands/core-bucket-c-hq-detach-native.d.ts +43 -0
- package/dist/commands/core-bucket-c-hq-detach-native.js +241 -0
- package/dist/commands/core-bucket-c-work-mesh-offer-native.js +8 -2
- package/dist/commands/core.js +12 -0
- package/dist/commands/daemon.js +2 -0
- package/dist/commands/lanes-accounts.js +3 -1
- package/dist/commands/lanes-shared.d.ts +7 -0
- package/dist/commands/lanes.js +139 -17
- package/dist/commands/mesh.js +32 -19
- package/dist/commands/skill.js +9 -4
- package/dist/fast-scaffold.js +28 -0
- package/dist/lib/bot/inbox-poll-backoff-flag.d.ts +3 -5
- package/dist/lib/bot/inbox-poll-backoff-flag.js +20 -12
- package/dist/lib/bot/inbox-wake.d.ts +18 -0
- package/dist/lib/bot/inbox-wake.js +125 -0
- package/dist/lib/bot/run.d.ts +8 -0
- package/dist/lib/bot/run.js +51 -7
- package/dist/lib/bot/runtime/messages-stream.js +31 -3
- package/dist/lib/capacity/lane-login.js +1 -0
- package/dist/lib/daemon/catalog.d.ts +4 -0
- package/dist/lib/daemon/catalog.js +6 -3
- package/dist/lib/daemon/flag-monitor.d.ts +4 -1
- package/dist/lib/daemon/flag-monitor.js +12 -6
- package/dist/lib/daemon/flag.d.ts +2 -0
- package/dist/lib/daemon/flag.js +11 -5
- package/dist/lib/daemon/hq-child-bootstrap.mjs +47 -7
- package/dist/lib/daemon/kill-switch-flags.d.ts +5 -0
- package/dist/lib/daemon/kill-switch-flags.js +5 -0
- package/dist/lib/daemon/lanes-reconcile-loader.d.ts +7 -0
- package/dist/lib/daemon/lanes-reconcile-loader.js +24 -0
- package/dist/lib/daemon/lanes-reconcile-watcher.d.ts +17 -0
- package/dist/lib/daemon/lanes-reconcile-watcher.js +80 -0
- package/dist/lib/daemon/remote-control.d.ts +8 -5
- package/dist/lib/daemon/remote-control.js +8 -7
- package/dist/lib/daemon/run.d.ts +4 -1
- package/dist/lib/daemon/run.js +133 -20
- package/dist/lib/doctor/json-output.d.ts +15 -3
- package/dist/lib/doctor/json-output.js +13 -1
- package/dist/lib/lanes/accounts.js +2 -2
- package/dist/lib/lanes/daemon-reconcile.d.ts +3 -0
- package/dist/lib/lanes/daemon-reconcile.js +8 -0
- package/dist/lib/lanes/host-capacity.d.ts +4 -0
- package/dist/lib/lanes/host-capacity.js +10 -1
- package/dist/lib/lanes/index.d.ts +2 -2
- package/dist/lib/lanes/index.js +1 -1
- package/dist/lib/lanes/loop.d.ts +8 -0
- package/dist/lib/lanes/loop.js +35 -0
- package/dist/lib/lanes/quota-notice.d.ts +11 -11
- package/dist/lib/lanes/quota-notice.js +20 -29
- package/dist/lib/lanes/quota.d.ts +69 -50
- package/dist/lib/lanes/quota.js +146 -127
- package/dist/lib/lanes/reconcile-result.d.ts +10 -0
- package/dist/lib/lanes/reconcile-result.js +11 -0
- package/dist/lib/lanes/reconcile.d.ts +14 -0
- package/dist/lib/lanes/reconcile.js +77 -23
- package/dist/lib/lanes/watcher.d.ts +8 -0
- package/dist/lib/lanes/watcher.js +62 -20
- package/dist/lib/mesh/live/daemon/work-subscribe.d.ts +1 -1
- package/dist/lib/mesh/live/daemon/work-subscribe.js +8 -1
- package/dist/lib/mesh/live/paths.d.ts +2 -0
- package/dist/lib/mesh/live/paths.js +2 -0
- package/dist/lib/mesh/story-status.d.ts +2 -2
- package/dist/lib/mesh/story-status.js +2 -1
- package/dist/utils/resident-package-preload.js +18 -4
- package/package.json +1 -1
|
@@ -437,6 +437,13 @@ export interface LaneAccountsHandlerDeps {
|
|
|
437
437
|
readClaudeAccountBalanceSignalsEnabled(ctx: Ctx): Promise<boolean>;
|
|
438
438
|
reconcileHostFromCtx(ctx: Ctx): ReconcileHost;
|
|
439
439
|
resolveCallerPath(callerCwd: string, filePath: string): string;
|
|
440
|
+
/** Admit queued lanes in-process after capacity changes; returns admitted lanes. */
|
|
441
|
+
admitQueuedFromCtx(ctx: Ctx): Promise<Array<{
|
|
442
|
+
id: string;
|
|
443
|
+
from?: string;
|
|
444
|
+
to?: string;
|
|
445
|
+
reason?: string;
|
|
446
|
+
}>>;
|
|
440
447
|
}
|
|
441
448
|
export interface LaneQuestionsHandlerDeps {
|
|
442
449
|
CAPACITY_PROBE_TIMEOUT_MS: number;
|
package/dist/commands/lanes.js
CHANGED
|
@@ -24,6 +24,7 @@ export { resolveAnswerChoice } from "./lanes-questions.js";
|
|
|
24
24
|
import { registerOutpostPrunerCommand } from "./outpost-pruner.js";
|
|
25
25
|
import { registerLaneKpisCommand } from "./lanes-kpis.js";
|
|
26
26
|
import { registerLaneKeepAliveAuditCommand } from "./lanes-keep-alive-audit.js";
|
|
27
|
+
import { finishReconcilePass } from "../lib/lanes/reconcile-result.js";
|
|
27
28
|
import { registerLaneAutopilotReportCommand } from "./lanes-autopilot.js";
|
|
28
29
|
import { registerLaneChecksCommand } from "./lanes-checks.js";
|
|
29
30
|
import { registerLaneDropboxRepairCommand } from "./lanes-dropbox-repair.js";
|
|
@@ -41,11 +42,12 @@ import { runResidentCommandWithPackageLease } from "../utils/resident-package-pr
|
|
|
41
42
|
import { codexEnvEvidence, grokEnvEvidence } from "../lib/doctor/platform.js";
|
|
42
43
|
import { readLanesFlagLocalOverride, readLanesRegistryFlag, readLanesRegistryFlagFailOff, readLanesRegistryFlagFailOpen } from "../lib/lanes/registry-flag.js";
|
|
43
44
|
import { readLaneStatusRowFields } from "../lib/lanes/status-fields.js";
|
|
45
|
+
import { registerDaemonLanesReconcileHandler } from "../lib/lanes/daemon-reconcile.js";
|
|
44
46
|
import { appendProjectFocusOverride, readProjectStoryFocusData, removeProjectFocusOverride } from "../lib/lanes/story-ledger.js";
|
|
45
47
|
import { appendLaneFocusOverride, assertFocusGuardAllows, makeFocusOverride } from "../lib/lanes/focus-guard.js";
|
|
46
48
|
import { LANE_FOCUS_GUARD_FLAG, LANE_FOCUS_DASHBOARD_FLAG, 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_PROFILE_PIN_EXHAUSTED_FALLBACK_FLAG, LANE_STATUS_ROW_FIELDS_FLAG, LANE_REAP_STOP_FLAG, LANE_REUSE_REFRESHES_PROFILE_FLAG, LANE_WORKER_CONTINUITY_FLAG, LANE_CONDUCT_LOOP_FLAG, LANE_ENVELOPE_REPAIR_GUIDANCE_FLAG, } from "../lib/lanes/flag-keys.js";
|
|
47
49
|
import { findWorkerContinuityLane, sameLaneHost, workerContinuityPrompt } from "../lib/lanes/worker-continuity.js";
|
|
48
|
-
import { enqueueLoopEnvelope, interruptLoopQueue, interruptLoopQueueForStory, loopControllerIsAlive, loopStatus, validateLoopEnvelope } from "../lib/lanes/loop.js";
|
|
50
|
+
import { commitIdleLoopStop, enqueueLoopEnvelope, interruptLoopQueue, interruptLoopQueueForStory, loopControllerIsAlive, loopStatus, validateLoopEnvelope } from "../lib/lanes/loop.js";
|
|
49
51
|
import { runLaneLoopController, startLaneLoopController } from "./lanes-loop.js";
|
|
50
52
|
import { configuredCodexRolloutHomes, retainCodexRollouts } from "../lib/lanes/disk-guard.js";
|
|
51
53
|
import { isControllerAliasOutpostId } from "../lib/lanes/admission-host.js";
|
|
@@ -76,6 +78,7 @@ import { listLaneReviews } from "../lib/lanes/reviews.js";
|
|
|
76
78
|
import { effectiveAccountHome } from "../lib/lanes/account-home.js";
|
|
77
79
|
import { remoteControlSelectionConfig, remoteControlSessionHome } from "../lib/lanes/remote-control-lane.js";
|
|
78
80
|
import { AccountResolutionError, compareLaneQueueOrder, LANE_PROVIDERS, LANE_STATES, QUESTION_STATUSES, SENIOR_KINDS, accountStatus, appendCappedHistory, canonicalizeHome, createLane, decideAdmission, defaultLivenessDeps, defaultSystemdUserDir, defaultThrottleDeps, installReconcileTimer, providerPathEnv, probeDrainHookRegistration, isLanesError, isLaneVersionConflict, isTerminalLaneState, isFinishedResumableHireChild, childrenHoldingHireGrantCarve, laneHoldsHireGrantCarve, assignedChildHireGrants, hireGrantCapacityError, planHireGrantBackfill, terminalChildResumeHireGrantError, withHireGrantAdmission, laneStoryLedgerEnabled, syncLaneToProjectStoryLedger, removeLaneFromProjectStoryLedger, validateProjectStories, buildLaneStatusSnapshot, formatLaneStatusHuman, listLaneIds, listQuestionIds, loadLanesConfig, laneRunsHere, MAX_LANE_DEPTH, MONITOR_ERROR_EXIT_CODE, readLiveMonitorEvidence, resolveMachineIdentity as lookupMachineIdentity, loadLivenessIndex, parseLaneProvider, isLaneProvider, parseLaneRecord, parseLaneState, parseQuestionRecord, parseSeniorKind, readAllLanes, readLane, sanitizeHostComponent, retryUpdateLane, syncLaneRecordFromOwner, readQuestion, resolveAccount, resolveLaneWorker, ignoredWorkerProfileFields, loadWorkerProfile, loadWorkerProfileWithRegistry, registryWorkerRecord, runReconcilePass, DEAD_HOST_MS, sessionLiveness, tryReadLane, uninstallReconcileTimer, updateLane, updateQuestion, dropboxDir, laneDeliveryMechanism, hasActiveAdmissionReservation, hasActivePendingResume, hasRecordedSessionId, hasEarlierEligibleQueuedLane, laneAdmissionCapReason, providerSupportsSessionResume, providerSessionPortable, isFailedQuotaKeepAliveLane, sessionNotPortableMessage, withLaneAdmissionLock, withAllLaneAdmissionLocks, readWorkerRunResult, resumeCommandRefusal, withLaneHireLocks, raiseLaneQuestion, sha256Text, } from "../lib/lanes/index.js";
|
|
81
|
+
import { admitQueuedNow } from "../lib/lanes/reconcile.js";
|
|
79
82
|
import { laneStories, storyWarning, } from "../lib/lanes/stories.js";
|
|
80
83
|
import { resolveLaneKeepAlive } from "../lib/lanes/profile.js";
|
|
81
84
|
import { laneCompanyUidSource, resolveLaneCompany } from "../lib/lanes/lane-company.js";
|
|
@@ -490,6 +493,82 @@ function livenessDepsFromCtx(ctx) {
|
|
|
490
493
|
hostname: ctx.hostname,
|
|
491
494
|
};
|
|
492
495
|
}
|
|
496
|
+
/**
|
|
497
|
+
* Admit queued lanes in-process after a command frees or adds capacity, so
|
|
498
|
+
* the queue drains without `hq daemon`. Best effort: an admission failure is
|
|
499
|
+
* reported on stderr and never fails the command that freed the slot.
|
|
500
|
+
*/
|
|
501
|
+
async function admitQueuedFromCtx(ctx) {
|
|
502
|
+
try {
|
|
503
|
+
const result = await admitQueuedNow(ctx.hqRoot(), {
|
|
504
|
+
now: ctx.now,
|
|
505
|
+
host: reconcileHostFromCtx(ctx),
|
|
506
|
+
dryRun: false,
|
|
507
|
+
spawnLaneDeps: {
|
|
508
|
+
env: ctx.env,
|
|
509
|
+
existsSync: ctx.existsSync,
|
|
510
|
+
spawnProcess: ctx.spawnProcess,
|
|
511
|
+
proveDetached: ctx.proveDetached,
|
|
512
|
+
killProcess: ctx.killProcess,
|
|
513
|
+
now: ctx.now,
|
|
514
|
+
resolveMachineIdentity: ctx.resolveMachineIdentity,
|
|
515
|
+
runCompaction: ctx.runCompaction,
|
|
516
|
+
locateTranscript: ctx.locateTranscript,
|
|
517
|
+
},
|
|
518
|
+
throttleDeps: ctx.throttleDeps,
|
|
519
|
+
livenessDeps: livenessDepsFromCtx(ctx),
|
|
520
|
+
presenceConnected: ctx.presenceConnected,
|
|
521
|
+
mesh: ctx.mesh,
|
|
522
|
+
env: ctx.env,
|
|
523
|
+
});
|
|
524
|
+
for (const error of result.errors) {
|
|
525
|
+
process.stderr.write(`hq lanes: queue admission: ${error.message}\n`);
|
|
526
|
+
}
|
|
527
|
+
return result.admitted;
|
|
528
|
+
}
|
|
529
|
+
catch (err) {
|
|
530
|
+
process.stderr.write(`hq lanes: queue admission failed: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
531
|
+
return [];
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* End a queued loop lane whose queue holds only a stop envelope and whose
|
|
536
|
+
* controller is not running. Without this the lane waits for admission just
|
|
537
|
+
* to read the stop, and counts as busy for its worker until then.
|
|
538
|
+
*/
|
|
539
|
+
async function finalizeIdleLoopStop(ctx, lane) {
|
|
540
|
+
if (lane.loop_mode !== true || lane.state !== "queued")
|
|
541
|
+
return undefined;
|
|
542
|
+
const hqRoot = ctx.hqRoot();
|
|
543
|
+
const runDirPath = runDir(hqRoot, lane.lane_id);
|
|
544
|
+
if (loopControllerIsAlive(runDirPath))
|
|
545
|
+
return undefined;
|
|
546
|
+
if (!commitIdleLoopStop(runDirPath, lane.lane_id, ctx.now))
|
|
547
|
+
return undefined;
|
|
548
|
+
let stopped;
|
|
549
|
+
try {
|
|
550
|
+
stopped = casUpdateLane(hqRoot, lane.lane_id, (current) => {
|
|
551
|
+
if (current.state !== "queued") {
|
|
552
|
+
throw new LanesError("lane_state_changed", `Lane ${lane.lane_id} left the queue while its stop was committed`, { lane_id: lane.lane_id, state: current.state });
|
|
553
|
+
}
|
|
554
|
+
return {
|
|
555
|
+
...current,
|
|
556
|
+
state: "done",
|
|
557
|
+
queued_reason: undefined,
|
|
558
|
+
queued_details: undefined,
|
|
559
|
+
admission_reserved_at: undefined,
|
|
560
|
+
terminal_reason: "loop_stopped",
|
|
561
|
+
};
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
catch (err) {
|
|
565
|
+
if (err instanceof LanesError && err.error === "lane_state_changed")
|
|
566
|
+
return undefined;
|
|
567
|
+
throw err;
|
|
568
|
+
}
|
|
569
|
+
await emitLaneTerminalStateSoft(ctx, stopped);
|
|
570
|
+
return stopped;
|
|
571
|
+
}
|
|
493
572
|
function reconcileHostFromCtx(ctx) {
|
|
494
573
|
return resolveAdmissionHost({
|
|
495
574
|
hostname: ctx.hostname,
|
|
@@ -3522,6 +3601,17 @@ async function runCreate(ctx, opts) {
|
|
|
3522
3601
|
throw new LanesError("lane_title_requires_remote_control", "--title is only supported with --remote-control", {});
|
|
3523
3602
|
}
|
|
3524
3603
|
const continuityEnabled = opts.remoteControl !== true && opts.worker !== undefined && await readLanesRegistryFlagFailOpen(LANE_WORKER_CONTINUITY_FLAG, { company: company ?? meshCompany, env: ctx.env, defaultValue: true });
|
|
3604
|
+
// A lane that waits only on the admitter (a queued loop lane holding just a
|
|
3605
|
+
// stop, or a queued lane with free capacity) is not busy: finish it here.
|
|
3606
|
+
const preCreateAdmitted = [];
|
|
3607
|
+
if (continuityEnabled) {
|
|
3608
|
+
const workerId = resolvedWorker?.id ?? opts.worker;
|
|
3609
|
+
const waiting = loadAllLanes(hqRoot).filter((lane) => lane.worker === workerId && lane.provider === provider && lane.state === "queued");
|
|
3610
|
+
for (const lane of waiting)
|
|
3611
|
+
await finalizeIdleLoopStop(ctx, lane);
|
|
3612
|
+
if (waiting.length > 0)
|
|
3613
|
+
preCreateAdmitted.push(...await admitQueuedFromCtx(ctx));
|
|
3614
|
+
}
|
|
3525
3615
|
let workerContinuity = continuityEnabled
|
|
3526
3616
|
? findWorkerContinuityLane(loadAllLanes(hqRoot), {
|
|
3527
3617
|
senior,
|
|
@@ -4337,10 +4427,19 @@ async function runCreate(ctx, opts) {
|
|
|
4337
4427
|
: undefined,
|
|
4338
4428
|
});
|
|
4339
4429
|
}
|
|
4430
|
+
// Admit queued lanes (older ones first) now that this create has settled.
|
|
4431
|
+
// Outpost lanes are admitted on their Outpost.
|
|
4432
|
+
const admitted = [...preCreateAdmitted];
|
|
4433
|
+
if (!outpostId) {
|
|
4434
|
+
admitted.push(...await admitQueuedFromCtx(ctx));
|
|
4435
|
+
if (admitted.some((entry) => entry.id === started.lane_id))
|
|
4436
|
+
started = readLane(hqRoot, started.lane_id);
|
|
4437
|
+
}
|
|
4340
4438
|
if (!opts.quiet)
|
|
4341
4439
|
printJson({
|
|
4342
4440
|
ok: true,
|
|
4343
4441
|
action: "create",
|
|
4442
|
+
admitted,
|
|
4344
4443
|
lane_id: started.lane_id,
|
|
4345
4444
|
state: started.state,
|
|
4346
4445
|
queued_reason: started.queued_reason ?? null,
|
|
@@ -7410,7 +7509,7 @@ async function prepareAccountMove(ctx, lane, input) {
|
|
|
7410
7509
|
});
|
|
7411
7510
|
const block = quotaBlockFor(loadQuotaState(hqRoot), lane.provider, target, model, now);
|
|
7412
7511
|
if (block.blocked) {
|
|
7413
|
-
throw new LanesError("account_quota_held", `Account ${target} for ${lane.provider}
|
|
7512
|
+
throw new LanesError("account_quota_held", `Account ${target} for ${lane.provider} cannot run model ${model ?? "(default)"}: the account's model needs credits${block.marker ? ` (${block.marker})` : ""}. Once credits are added, clear the marker with: hq lanes accounts clear-quota ${lane.provider} ${target}`, { provider: lane.provider, account: target, quota_reset_at: block.quota_reset_at ?? null, marker: block.marker ?? null, model: model ?? null, clear_command: `hq lanes accounts clear-quota ${lane.provider} ${target}` });
|
|
7414
7513
|
}
|
|
7415
7514
|
if (model !== undefined) {
|
|
7416
7515
|
validateLaneModel(lane.provider, model, targetHome, {
|
|
@@ -8705,8 +8804,18 @@ async function runStop(ctx, laneId, reason, quiet = false) {
|
|
|
8705
8804
|
const queued = enqueueLoopEnvelope({ runDir: runDirPath, laneId: lane.lane_id, envelope: { kind: "stop" }, now: ctx.now });
|
|
8706
8805
|
if (!controllerAlive && lane.state !== "queued")
|
|
8707
8806
|
startLaneLoopController(ctx, lane.lane_id);
|
|
8807
|
+
const finalized = !controllerAlive ? await finalizeIdleLoopStop(ctx, readLane(hqRoot, lane.lane_id)) : undefined;
|
|
8808
|
+
const admitted = await admitQueuedFromCtx(ctx);
|
|
8708
8809
|
if (!quiet)
|
|
8709
|
-
printJson({
|
|
8810
|
+
printJson({
|
|
8811
|
+
ok: true,
|
|
8812
|
+
action: "stop",
|
|
8813
|
+
lane_id: lane.lane_id,
|
|
8814
|
+
terminal: finalized !== undefined,
|
|
8815
|
+
queued_stop: queued,
|
|
8816
|
+
...(finalized ? { lane: finalized } : {}),
|
|
8817
|
+
admitted,
|
|
8818
|
+
});
|
|
8710
8819
|
return;
|
|
8711
8820
|
}
|
|
8712
8821
|
if (isTerminalLaneState(lane.state)) {
|
|
@@ -8744,6 +8853,7 @@ async function runStop(ctx, laneId, reason, quiet = false) {
|
|
|
8744
8853
|
}
|
|
8745
8854
|
await emitLaneTerminalStateSoft(ctx, updated);
|
|
8746
8855
|
const cancelled = cancelPendingQuestionsForLane(hqRoot, laneId, at);
|
|
8856
|
+
const admitted = await admitQueuedFromCtx(ctx);
|
|
8747
8857
|
if (!quiet)
|
|
8748
8858
|
printJson({
|
|
8749
8859
|
ok: true,
|
|
@@ -8752,6 +8862,7 @@ async function runStop(ctx, laneId, reason, quiet = false) {
|
|
|
8752
8862
|
terminal: true,
|
|
8753
8863
|
resumable: false,
|
|
8754
8864
|
cancelled_questions: cancelled.map((q) => q.question_id),
|
|
8865
|
+
admitted,
|
|
8755
8866
|
});
|
|
8756
8867
|
}
|
|
8757
8868
|
/** Stderr notice that `stop` ends a lane for good, naming the resumable path. */
|
|
@@ -9429,21 +9540,21 @@ async function runReconcile(ctx, opts, recoverQueuedMessages) {
|
|
|
9429
9540
|
summary.errors.push({ code: error instanceof LanesError ? error.error : "lead_autopilot_failed", message });
|
|
9430
9541
|
process.stderr.write(`hq lanes autopilot: ${message}\n`);
|
|
9431
9542
|
}
|
|
9432
|
-
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
process.exit(1);
|
|
9543
|
+
if (!opts.inProcess) {
|
|
9544
|
+
printJson({
|
|
9545
|
+
...summary,
|
|
9546
|
+
...(autopilotRegistrySync ? { autopilot_registry_sync: autopilotRegistrySync } : {}),
|
|
9547
|
+
...(autopilot ? { autopilot } : {}),
|
|
9548
|
+
...(remoteLost.length > 0 ? { remote_lost: remoteLost } : {}),
|
|
9549
|
+
...(mirrorRefresh.unverifiedRemote.size > 0
|
|
9550
|
+
? {
|
|
9551
|
+
unverified_remote_lanes: [...mirrorRefresh.unverifiedRemote.keys()]
|
|
9552
|
+
.filter((id) => !terminalizedRemoteIds.has(id)),
|
|
9553
|
+
}
|
|
9554
|
+
: {}),
|
|
9555
|
+
});
|
|
9446
9556
|
}
|
|
9557
|
+
finishReconcilePass(summary, opts.inProcess ? "daemon" : "cli");
|
|
9447
9558
|
}
|
|
9448
9559
|
async function runReconcileInstall(ctx, opts) {
|
|
9449
9560
|
// `hq daemon` runs lanes-reconcile on this machine; a separate timer would run it twice.
|
|
@@ -9540,6 +9651,7 @@ export function registerLanesCommand(parent, deps = {}) {
|
|
|
9540
9651
|
readClaudeAccountBalanceSignalsEnabled,
|
|
9541
9652
|
reconcileHostFromCtx,
|
|
9542
9653
|
resolveCallerPath,
|
|
9654
|
+
admitQueuedFromCtx,
|
|
9543
9655
|
});
|
|
9544
9656
|
const questionHandlers = createLaneQuestionsHandlers({
|
|
9545
9657
|
CAPACITY_PROBE_TIMEOUT_MS,
|
|
@@ -9647,6 +9759,16 @@ export function registerLanesCommand(parent, deps = {}) {
|
|
|
9647
9759
|
withResumeHireAdmission,
|
|
9648
9760
|
};
|
|
9649
9761
|
const messageHandlers = createLaneMessageHandlers(messageHandlerDeps);
|
|
9762
|
+
const daemonReconcileCtx = { ...ctx, env: { ...ctx.env } };
|
|
9763
|
+
registerDaemonLanesReconcileHandler(async () => {
|
|
9764
|
+
const hqRoot = daemonReconcileCtx.hqRoot();
|
|
9765
|
+
daemonReconcileCtx.env.HQ_ROOT = hqRoot;
|
|
9766
|
+
daemonReconcileCtx.cwd = () => hqRoot;
|
|
9767
|
+
daemonReconcileCtx.callerCwd = () => hqRoot;
|
|
9768
|
+
await runReconcile(daemonReconcileCtx, { inProcess: true }, async (lane) => {
|
|
9769
|
+
await messageHandlers.recoverQueuedMessages(daemonReconcileCtx, lane.lane_id);
|
|
9770
|
+
});
|
|
9771
|
+
});
|
|
9650
9772
|
monitorLaneMessageApis.set(parent, (laneId, payload) => messageHandlers.deliverMonitorLaneMessage(ctx, laneId, payload));
|
|
9651
9773
|
const resumeHandlers = createLaneResumeHandlers({
|
|
9652
9774
|
onLaneWorkerStarted: deps.onLaneWorkerStarted,
|
package/dist/commands/mesh.js
CHANGED
|
@@ -307,16 +307,21 @@ function parseProjectReposJson(raw, source) {
|
|
|
307
307
|
throw err;
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
|
-
function projectStoriesFromJson(value, source) {
|
|
310
|
+
function projectStoriesFromJson(value, source, options = {}) {
|
|
311
311
|
const plan = Array.isArray(value) ? null : record(value);
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
312
|
+
if (options.requireUserStories && (!plan || !Array.isArray(plan.userStories))) {
|
|
313
|
+
fail(`${source} must be a PRD object with a userStories array.`);
|
|
314
|
+
}
|
|
315
|
+
const rawStories = options.requireUserStories
|
|
316
|
+
? plan?.userStories ?? null
|
|
317
|
+
: Array.isArray(value)
|
|
318
|
+
? value
|
|
319
|
+
: Array.isArray(plan?.userStories)
|
|
320
|
+
? plan.userStories
|
|
321
|
+
: Array.isArray(plan?.stories)
|
|
322
|
+
? plan.stories
|
|
323
|
+
: null;
|
|
324
|
+
if (!Array.isArray(rawStories)) {
|
|
320
325
|
fail(`${source} must be a JSON story array or an object with userStories.`);
|
|
321
326
|
}
|
|
322
327
|
const rejectedStories = [];
|
|
@@ -398,7 +403,7 @@ function failProjectStoryStates(rejected, json) {
|
|
|
398
403
|
}
|
|
399
404
|
function parseProjectPlan(raw, source, options = {}) {
|
|
400
405
|
try {
|
|
401
|
-
const plan = projectStoriesFromJson(JSON.parse(raw), source);
|
|
406
|
+
const plan = projectStoriesFromJson(JSON.parse(raw), source, options);
|
|
402
407
|
if (plan.rejectedStories.length && !options.allowRejectedStories) {
|
|
403
408
|
throw new RejectedProjectStoryStatesError(plan.rejectedStories);
|
|
404
409
|
}
|
|
@@ -431,7 +436,7 @@ async function runProjectSet(projectId, opts) {
|
|
|
431
436
|
fail("Pass only one of --repos-json or --repo.");
|
|
432
437
|
}
|
|
433
438
|
const source = opts.storiesFile
|
|
434
|
-
? parseProjectPlan(readFileSync(opts.storiesFile, "utf8"), opts.storiesFile)
|
|
439
|
+
? parseProjectPlan(readFileSync(opts.storiesFile, "utf8"), opts.storiesFile, { requireUserStories: true })
|
|
435
440
|
: opts.storiesJson
|
|
436
441
|
? parseProjectPlan(opts.storiesJson, "--stories-json")
|
|
437
442
|
: undefined;
|
|
@@ -588,12 +593,17 @@ async function runProjectMemberAdd(projectId, personUid, opts) {
|
|
|
588
593
|
async function runProjectEnsure(projectId, opts) {
|
|
589
594
|
if (!opts.storiesFile?.trim())
|
|
590
595
|
fail("`--stories-file <prd.json>` is required.");
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
596
|
+
let source;
|
|
597
|
+
try {
|
|
598
|
+
source = parseProjectPlan(readFileSync(opts.storiesFile, "utf8"), opts.storiesFile, { requireUserStories: true });
|
|
599
|
+
}
|
|
600
|
+
catch (err) {
|
|
601
|
+
if (!(err instanceof RejectedProjectStoryStatesError) || !opts.json)
|
|
602
|
+
throw err;
|
|
603
|
+
failProjectStoryStates(err.rejected, true);
|
|
595
604
|
return;
|
|
596
605
|
}
|
|
606
|
+
const { token, company } = await withCompany(opts);
|
|
597
607
|
let current;
|
|
598
608
|
try {
|
|
599
609
|
current = await getProjectView(token, company.companyUid, projectId);
|
|
@@ -738,7 +748,10 @@ async function runProjectEnsure(projectId, opts) {
|
|
|
738
748
|
async function runProjectReconcile(projectId, opts) {
|
|
739
749
|
if (!opts.storiesFile?.trim())
|
|
740
750
|
fail("`--stories-file <prd.json>` is required.");
|
|
741
|
-
const source = parseProjectPlan(readFileSync(opts.storiesFile, "utf8"), opts.storiesFile, {
|
|
751
|
+
const source = parseProjectPlan(readFileSync(opts.storiesFile, "utf8"), opts.storiesFile, {
|
|
752
|
+
requireUserStories: true,
|
|
753
|
+
allowRejectedStories: true,
|
|
754
|
+
});
|
|
742
755
|
const { token, company } = await withCompany(opts);
|
|
743
756
|
let current;
|
|
744
757
|
try {
|
|
@@ -852,7 +865,7 @@ async function runPrdSync(opts) {
|
|
|
852
865
|
return;
|
|
853
866
|
}
|
|
854
867
|
try {
|
|
855
|
-
const source = parseProjectPlan(readFileSync(file, "utf8"), file);
|
|
868
|
+
const source = parseProjectPlan(readFileSync(file, "utf8"), file, { requireUserStories: true });
|
|
856
869
|
await ensureMissingBoardStories({
|
|
857
870
|
token,
|
|
858
871
|
company: {
|
|
@@ -1091,7 +1104,7 @@ async function runBindProject(target, opts) {
|
|
|
1091
1104
|
}
|
|
1092
1105
|
if (!current.companyUid)
|
|
1093
1106
|
fail(`Session ${sessionId} has no company. Bind a company first.`);
|
|
1094
|
-
const plan = parseProjectPlan(readFileSync(prdPath, "utf8"), prdPath);
|
|
1107
|
+
const plan = parseProjectPlan(readFileSync(prdPath, "utf8"), prdPath, { requireUserStories: true });
|
|
1095
1108
|
const { token, company } = await withCompany({ company: opts.company ?? current.companySlug });
|
|
1096
1109
|
await ensureProjectBoard({
|
|
1097
1110
|
token,
|
|
@@ -1234,7 +1247,7 @@ async function runContextReconcile(opts) {
|
|
|
1234
1247
|
validateMembership,
|
|
1235
1248
|
ensureProjectBoard: token
|
|
1236
1249
|
? async ({ companyUid, projectId, prdPath }) => {
|
|
1237
|
-
const plan = parseProjectPlan(readFileSync(prdPath, "utf8"), prdPath);
|
|
1250
|
+
const plan = parseProjectPlan(readFileSync(prdPath, "utf8"), prdPath, { requireUserStories: true });
|
|
1238
1251
|
await ensureProjectBoard({
|
|
1239
1252
|
token,
|
|
1240
1253
|
company: { companyUid, companySlug: companyUid },
|
package/dist/commands/skill.js
CHANGED
|
@@ -190,16 +190,21 @@ function displayNameFromSlug(slug) {
|
|
|
190
190
|
.join(" ");
|
|
191
191
|
}
|
|
192
192
|
export function makeSkillTemplate(input) {
|
|
193
|
-
|
|
193
|
+
// Frontmatter `name` is the slash-command name in Claude Code and Codex, so it
|
|
194
|
+
// must be the slug. A spaced display title there breaks command entry in the
|
|
195
|
+
// Claude desktop app. The display title goes in frontmatter `title` (which
|
|
196
|
+
// HQ Pro shows in the console) and in the heading.
|
|
197
|
+
const title = input.name?.trim() || displayNameFromSlug(input.slug);
|
|
194
198
|
const description = input.description?.trim() ?? "";
|
|
195
199
|
return [
|
|
196
200
|
"---",
|
|
197
|
-
`name: ${JSON.stringify(
|
|
201
|
+
`name: ${JSON.stringify(input.slug)}`,
|
|
202
|
+
`title: ${JSON.stringify(title)}`,
|
|
198
203
|
`description: ${JSON.stringify(description)}`,
|
|
199
204
|
"tags: []",
|
|
200
205
|
"---",
|
|
201
206
|
"",
|
|
202
|
-
`# ${
|
|
207
|
+
`# ${title}`,
|
|
203
208
|
"",
|
|
204
209
|
"Describe when and how to use this skill.",
|
|
205
210
|
"",
|
|
@@ -466,7 +471,7 @@ export function registerSkillCommand(program, deps = {}) {
|
|
|
466
471
|
skill
|
|
467
472
|
.command("create <slug>")
|
|
468
473
|
.description("Register, stamp, surface, and sync a company skill")
|
|
469
|
-
.option("--name <name>", "Display
|
|
474
|
+
.option("--name <name>", "Display title for a new template, written as frontmatter title (frontmatter name is always the slug)")
|
|
470
475
|
.option("--description <text>", "Description when creating a new template")
|
|
471
476
|
.option("--no-sync", "Register locally without uploading the stamped file")
|
|
472
477
|
.option("--surface-only", "Refresh local skill discovery without registration or sync")
|
package/dist/fast-scaffold.js
CHANGED
|
@@ -160,6 +160,30 @@ export function isDefaultOnFastFamily(flagKey) {
|
|
|
160
160
|
}
|
|
161
161
|
/** The relocated scripts that qualify for the entrypoint fast path. */
|
|
162
162
|
export const FAST_SCAFFOLD_SCRIPTS = [
|
|
163
|
+
{
|
|
164
|
+
name: "hq-detach",
|
|
165
|
+
kind: "native",
|
|
166
|
+
modulePath: "./commands/core-bucket-c-hq-detach-fast.js",
|
|
167
|
+
exportName: "runHqDetachFast",
|
|
168
|
+
flagKey: "hq-core-native-fast-route",
|
|
169
|
+
familyFlagKey: "core-native-bucket-c",
|
|
170
|
+
asset: "core/scripts/hq-detach.sh",
|
|
171
|
+
root: "cwd",
|
|
172
|
+
shellCwd: "caller",
|
|
173
|
+
shellHqRoot: "none",
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: "handoff-knowledge-commit",
|
|
177
|
+
kind: "native",
|
|
178
|
+
modulePath: "./commands/core-bucket-c-handoff-knowledge-fast.js",
|
|
179
|
+
exportName: "runHandoffKnowledgeCommitFast",
|
|
180
|
+
flagKey: "hq-core-native-fast-route",
|
|
181
|
+
familyFlagKey: "core-native-bucket-c",
|
|
182
|
+
asset: "core/scripts/handoff-knowledge-commit.sh",
|
|
183
|
+
root: "cwd",
|
|
184
|
+
shellCwd: "caller",
|
|
185
|
+
shellHqRoot: "none",
|
|
186
|
+
},
|
|
163
187
|
{
|
|
164
188
|
name: "work-mesh-project-registration-offer",
|
|
165
189
|
kind: "native",
|
|
@@ -897,6 +921,10 @@ export function isFastCoreRequest(argv) {
|
|
|
897
921
|
}
|
|
898
922
|
/** Metadata-only help can render without importing the selected command graph. */
|
|
899
923
|
export function isCommandHelpRequest(argv) {
|
|
924
|
+
// `core` owns the argument parser even when global options appear before
|
|
925
|
+
// its subcommand; its child commands pass --help through to their handlers.
|
|
926
|
+
if (argv[2] === "core" || argv[2] === "run")
|
|
927
|
+
return false;
|
|
900
928
|
const args = argv.slice(2);
|
|
901
929
|
const delimiter = args.indexOf("--");
|
|
902
930
|
const beforeDelimiter = delimiter === -1 ? args : args.slice(0, delimiter);
|
|
@@ -2,6 +2,8 @@ import { type FlagClient, type FlagClientOptions } from "@indigoai-us/hq-flags-c
|
|
|
2
2
|
import { type BotConfig } from "./config.js";
|
|
3
3
|
export declare const INBOX_POLL_BACKOFF_FLAG = "agents.inbox-poll-backoff-local-cli";
|
|
4
4
|
export declare const INBOX_POLL_BACKOFF_FLAG_FALLBACK = false;
|
|
5
|
+
export declare const INBOX_MQTT_WAKE_FLAG = "agents.bot-inbox-mqtt-wake";
|
|
6
|
+
export declare const INBOX_MQTT_WAKE_FLAG_FALLBACK = true;
|
|
5
7
|
export declare const INBOX_POLL_BACKOFF_FLAG_TIMEOUT_MS = 2000;
|
|
6
8
|
export declare const INBOX_POLL_BACKOFF_FLAG_CACHE_MS: number;
|
|
7
9
|
type InboxPollBackoffFlagClient = Pick<FlagClient, "ready" | "isEnabled" | "close">;
|
|
@@ -14,11 +16,7 @@ export interface InboxPollBackoffFlagReaderDependencies {
|
|
|
14
16
|
reportFailure?: (error: unknown) => void;
|
|
15
17
|
}
|
|
16
18
|
export declare function safeErrorClass(error: unknown): string;
|
|
17
|
-
/**
|
|
18
|
-
* Create a per-bot reader. The flag client is opened at most once per three
|
|
19
|
-
* minutes; a missing identity, failed request, or malformed snapshot keeps
|
|
20
|
-
* idle polling at its existing two-second interval.
|
|
21
|
-
*/
|
|
22
19
|
export declare function createInboxPollBackoffFlagReader(config: Pick<BotConfig, "kind" | "workerId" | "companies" | "companySlug" | "hqRoot">, dependencies?: InboxPollBackoffFlagReaderDependencies): () => Promise<boolean>;
|
|
20
|
+
export declare function createInboxMqttWakeFlagReader(config: Pick<BotConfig, "kind" | "workerId" | "companies" | "companySlug" | "hqRoot">, dependencies?: InboxPollBackoffFlagReaderDependencies): () => Promise<boolean>;
|
|
23
21
|
export {};
|
|
24
22
|
//# sourceMappingURL=inbox-poll-backoff-flag.d.ts.map
|
|
@@ -5,6 +5,8 @@ import { resolveFlagRegistryEndpoint } from "../flag-registry-endpoint.js";
|
|
|
5
5
|
import { effectiveBotCompanies, effectiveBotKind } from "./config.js";
|
|
6
6
|
export const INBOX_POLL_BACKOFF_FLAG = "agents.inbox-poll-backoff-local-cli";
|
|
7
7
|
export const INBOX_POLL_BACKOFF_FLAG_FALLBACK = false;
|
|
8
|
+
export const INBOX_MQTT_WAKE_FLAG = "agents.bot-inbox-mqtt-wake";
|
|
9
|
+
export const INBOX_MQTT_WAKE_FLAG_FALLBACK = true;
|
|
8
10
|
// One read every three minutes on a fresh connection. From a home network the
|
|
9
11
|
// TCP and TLS handshakes plus the resolve call take about 250-400 ms, so a
|
|
10
12
|
// 150 ms budget timed out on every read and kept the gate off.
|
|
@@ -15,8 +17,8 @@ export function safeErrorClass(error) {
|
|
|
15
17
|
const name = error instanceof Error ? error.name : "UnknownError";
|
|
16
18
|
return /^[A-Za-z][A-Za-z0-9]{0,63}$/.test(name) ? name : "UnknownError";
|
|
17
19
|
}
|
|
18
|
-
function reportFlagFailure(error) {
|
|
19
|
-
process.stderr.write(`HQ local bot inbox
|
|
20
|
+
function reportFlagFailure(error, fallback) {
|
|
21
|
+
process.stderr.write(`HQ local bot inbox flag lookup failed (${safeErrorClass(error)}); using default ${fallback ? "on" : "off"}.\n`);
|
|
20
22
|
}
|
|
21
23
|
function companyContexts(config, env) {
|
|
22
24
|
if (effectiveBotKind(config) !== "company")
|
|
@@ -44,9 +46,9 @@ function companyContexts(config, env) {
|
|
|
44
46
|
/**
|
|
45
47
|
* Create a per-bot reader. The flag client is opened at most once per three
|
|
46
48
|
* minutes; a missing identity, failed request, or malformed snapshot keeps
|
|
47
|
-
*
|
|
49
|
+
* registered fallback.
|
|
48
50
|
*/
|
|
49
|
-
|
|
51
|
+
function createInboxFlagReader(config, flagKey, fallback, dependencies = {}) {
|
|
50
52
|
const env = dependencies.env ?? process.env;
|
|
51
53
|
const contexts = companyContexts(config, env);
|
|
52
54
|
const endpoint = resolveFlagRegistryEndpoint(undefined, env);
|
|
@@ -54,15 +56,15 @@ export function createInboxPollBackoffFlagReader(config, dependencies = {}) {
|
|
|
54
56
|
const createClient = dependencies.createClient ?? createFlagClient;
|
|
55
57
|
const getToken = dependencies.getToken ?? (() => loadCachedTokens()?.idToken ?? "");
|
|
56
58
|
const doFetch = dependencies.fetch ?? globalThis.fetch;
|
|
57
|
-
const report = dependencies.reportFailure ?? reportFlagFailure;
|
|
58
|
-
let cachedValue =
|
|
59
|
+
const report = dependencies.reportFailure ?? ((error) => reportFlagFailure(error, fallback));
|
|
60
|
+
let cachedValue = fallback;
|
|
59
61
|
let lastReadAt = Number.NEGATIVE_INFINITY;
|
|
60
62
|
let pending = null;
|
|
61
63
|
const readContext = async (context) => {
|
|
62
64
|
let client;
|
|
63
65
|
let failed = false;
|
|
64
66
|
let failureReported = false;
|
|
65
|
-
let enabled =
|
|
67
|
+
let enabled = fallback;
|
|
66
68
|
const reportFailureOnce = (error) => {
|
|
67
69
|
failed = true;
|
|
68
70
|
if (failureReported)
|
|
@@ -84,7 +86,7 @@ export function createInboxPollBackoffFlagReader(config, dependencies = {}) {
|
|
|
84
86
|
});
|
|
85
87
|
await client.ready();
|
|
86
88
|
if (!failed) {
|
|
87
|
-
enabled = resolveFlagGate(client,
|
|
89
|
+
enabled = resolveFlagGate(client, flagKey, { fallback }, () => fallback);
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
catch (error) {
|
|
@@ -98,12 +100,12 @@ export function createInboxPollBackoffFlagReader(config, dependencies = {}) {
|
|
|
98
100
|
reportFailureOnce(error);
|
|
99
101
|
}
|
|
100
102
|
}
|
|
101
|
-
return failed ?
|
|
103
|
+
return failed ? fallback : enabled;
|
|
102
104
|
};
|
|
103
105
|
const read = async () => {
|
|
104
106
|
if (!contexts || contexts.length === 0) {
|
|
105
|
-
report(new Error("local bot inbox
|
|
106
|
-
return
|
|
107
|
+
report(new Error("local bot inbox flag has no resolvable company identity"));
|
|
108
|
+
return fallback;
|
|
107
109
|
}
|
|
108
110
|
const values = await Promise.all(contexts.map(readContext));
|
|
109
111
|
return values.every(Boolean);
|
|
@@ -123,7 +125,7 @@ export function createInboxPollBackoffFlagReader(config, dependencies = {}) {
|
|
|
123
125
|
})
|
|
124
126
|
.catch((error) => {
|
|
125
127
|
report(error);
|
|
126
|
-
cachedValue =
|
|
128
|
+
cachedValue = fallback;
|
|
127
129
|
return cachedValue;
|
|
128
130
|
})
|
|
129
131
|
.finally(() => {
|
|
@@ -132,4 +134,10 @@ export function createInboxPollBackoffFlagReader(config, dependencies = {}) {
|
|
|
132
134
|
return pending;
|
|
133
135
|
};
|
|
134
136
|
}
|
|
137
|
+
export function createInboxPollBackoffFlagReader(config, dependencies = {}) {
|
|
138
|
+
return createInboxFlagReader(config, INBOX_POLL_BACKOFF_FLAG, INBOX_POLL_BACKOFF_FLAG_FALLBACK, dependencies);
|
|
139
|
+
}
|
|
140
|
+
export function createInboxMqttWakeFlagReader(config, dependencies = {}) {
|
|
141
|
+
return createInboxFlagReader(config, INBOX_MQTT_WAKE_FLAG, INBOX_MQTT_WAKE_FLAG_FALLBACK, dependencies);
|
|
142
|
+
}
|
|
135
143
|
//# sourceMappingURL=inbox-poll-backoff-flag.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
export { AGENT_INBOX_PUSH_STATE_BASENAME } from "../mesh/live/paths.js";
|
|
3
|
+
type WakeEvent = "wake" | "timeout" | "aborted";
|
|
4
|
+
type Watcher = Pick<fs.FSWatcher, "close"> & {
|
|
5
|
+
on?: (event: "error", listener: (error: Error) => void) => unknown;
|
|
6
|
+
};
|
|
7
|
+
export interface InboxWakeWatcher {
|
|
8
|
+
wait(delayMs: number, signal?: AbortSignal): Promise<WakeEvent>;
|
|
9
|
+
isLiveFor?(agentUid: string): boolean;
|
|
10
|
+
close(): void;
|
|
11
|
+
}
|
|
12
|
+
/** Watches the content-free Work Mesh inbox sequence, with a bounded poll fallback. */
|
|
13
|
+
export declare function createInboxWakeWatcher(root: string, options?: {
|
|
14
|
+
watch?: (root: string, listener: (event: string, filename: string | Buffer | null) => void) => Watcher;
|
|
15
|
+
onError?: (error: unknown) => void;
|
|
16
|
+
now?: () => number;
|
|
17
|
+
}): InboxWakeWatcher;
|
|
18
|
+
//# sourceMappingURL=inbox-wake.d.ts.map
|