@kontextmind/kxm 0.7.14 → 0.7.15

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.
@@ -11,7 +11,7 @@
11
11
  "name": "kxm",
12
12
  "source": "./plugins/kxm",
13
13
  "description": "Durable workflows, peer agents, and kxm tui",
14
- "version": "0.7.14",
14
+ "version": "0.7.15",
15
15
  "category": "development",
16
16
  "tags": ["kxm", "multi-agent", "workflows", "mcp"]
17
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextmind/kxm",
3
- "version": "0.7.14",
3
+ "version": "0.7.15",
4
4
  "description": "KXM local-first multi-agent orchestration and operator dashboard",
5
5
  "type": "module",
6
6
  "author": "KontextMind",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "kxm",
4
4
  "displayName": "KXM",
5
- "version": "0.7.14",
5
+ "version": "0.7.15",
6
6
  "description": "Headless multi-agent orchestration, durable workflows, and a live operator dashboard for Pi and Claude Code",
7
7
  "author": {
8
8
  "name": "KontextMind",
@@ -33101,6 +33101,7 @@ function verifyVnextMigration(projectRoot, options = {}) {
33101
33101
  }
33102
33102
 
33103
33103
  // plugins/kxm/src/cli/vnext.ts
33104
+ var vnextDriveCliSeams = {};
33104
33105
  var repoRoot3 = resolve20(fileURLToPath4(new URL("../../../../", import.meta.url)));
33105
33106
  function initPlanPayload(plan) {
33106
33107
  return {
@@ -33544,9 +33545,21 @@ async function cmdVnextRunDrive(runtime, runId, simulated) {
33544
33545
  print(runtime.io, runtime.json, { ok: true, command: "runs drive", dryRun: true, runId, mode }, `drive plan: run ${runId} in ${mode} mode (no events written)`);
33545
33546
  return 0;
33546
33547
  }
33547
- const supervisor = await ensureVnextSupervisor({ env: runtime.env });
33548
- const result = await vnextRuntimeRequest(supervisor, "POST", `/v1/runs/${encodeURIComponent(runId)}/drive?projectRoot=${encodeURIComponent(projectRoot)}`, { mode });
33549
- print(runtime.io, runtime.json, { ok: true, command: "runs drive", run: result.run, handoff: result.handoff, events: result.events }, `run ${runId}: ${result.run?.status ?? "driven"}`);
33548
+ const supervisor = await (vnextDriveCliSeams.ensureSupervisor ?? ensureVnextSupervisor)({ env: runtime.env });
33549
+ const result = await (vnextDriveCliSeams.runtimeRequest ?? vnextRuntimeRequest)(supervisor, "POST", `/v1/runs/${encodeURIComponent(runId)}/drive?projectRoot=${encodeURIComponent(projectRoot)}`, { mode });
33550
+ const driveId = result.driveId;
33551
+ const poll = result.poll;
33552
+ const status = result.status;
33553
+ if (typeof driveId !== "string" || driveId.length === 0 || typeof poll !== "string" || poll.length === 0 || status !== "accepted") {
33554
+ print(runtime.io, runtime.json, { ok: false, command: "runs drive", error: "run_drive_io_failed" }, "run drive failed because a local operation did not complete");
33555
+ return 1;
33556
+ }
33557
+ print(
33558
+ runtime.io,
33559
+ runtime.json,
33560
+ { ok: true, command: "runs drive", runId, driveId, poll, mode, status },
33561
+ `drive ${driveId}: accepted (poll ${poll})`
33562
+ );
33550
33563
  return 0;
33551
33564
  } catch (error) {
33552
33565
  if (error instanceof VnextConfigError) {
@@ -17036,7 +17036,7 @@ async function deliverInboxNotification(messageId, delivered, notify) {
17036
17036
  }
17037
17037
 
17038
17038
  // plugins/kxm/src/mcp-server.ts
17039
- var VERSION = "0.7.14";
17039
+ var VERSION = "0.7.15";
17040
17040
  var inbox = /* @__PURE__ */ new Map();
17041
17041
  var notifiedInbox = /* @__PURE__ */ new Set();
17042
17042
  var meshClient;
@@ -21877,6 +21877,32 @@ function vnextGateHold(storePath, runId) {
21877
21877
  function vnextAdmittedToken(storePath, runId) {
21878
21878
  return owners.get(storePath)?.admitted.get(runId)?.token;
21879
21879
  }
21880
+ function attachVnextDriveSession(storePath, runId, token, session) {
21881
+ const owner = record(storePath);
21882
+ const current = owner.admitted.get(runId);
21883
+ if (!current || current.token !== token) {
21884
+ throw runtimeError("run_events_illegal", runId, "drive session requires the exact admitted token");
21885
+ }
21886
+ if (current.driveSession) {
21887
+ throw runtimeError("run_busy", runId, `run ${runId} already has a drive session`);
21888
+ }
21889
+ current.driveSession = session;
21890
+ }
21891
+ function clearVnextDriveSession(storePath, runId, token) {
21892
+ const owner = owners.get(storePath);
21893
+ const current = owner?.admitted.get(runId);
21894
+ if (!current || current.token !== token) return;
21895
+ delete current.driveSession;
21896
+ }
21897
+ function vnextOpenDriveSessions(storePath) {
21898
+ const owner = owners.get(storePath);
21899
+ if (!owner) return [];
21900
+ const sessions = [];
21901
+ for (const current of owner.admitted.values()) {
21902
+ if (current.driveSession) sessions.push(current.driveSession);
21903
+ }
21904
+ return sessions;
21905
+ }
21880
21906
  function enqueueVnextScheduledRun(storePath, runId, configRevision, bound, start) {
21881
21907
  const owner = record(storePath);
21882
21908
  if (owner.admitted.has(runId) || owner.queue.some((item) => item.runId === runId)) {
@@ -22315,15 +22341,16 @@ function cancelVnextRun(context, runId, options = {}) {
22315
22341
  events.push(event);
22316
22342
  return event;
22317
22343
  };
22344
+ const cancelReason = options.reason ?? "operator_cancel";
22318
22345
  const activeAttempt = Boolean(folded.currentStep?.attemptId) || vnextFoldPanelAttemptIds(folded.currentStep).length > 0;
22319
22346
  push("run.cancel_requested", {
22320
22347
  actor: { kind: "runtime", id: context.homeRuntimeId },
22321
- reason: "operator_cancel"
22348
+ reason: cancelReason
22322
22349
  });
22323
22350
  let status = "cancelled";
22324
22351
  if (folded.status === "running" && activeAttempt) {
22325
22352
  status = "cancelling";
22326
- push("run.status_changed", { status: "cancelling", reason: "operator_cancel" });
22353
+ push("run.status_changed", { status: "cancelling", reason: cancelReason });
22327
22354
  const attemptIds = new Set(vnextFoldPanelAttemptIds(folded.currentStep));
22328
22355
  if (folded.currentStep?.attemptId) attemptIds.add(folded.currentStep.attemptId);
22329
22356
  for (const attemptId of attemptIds) {
@@ -22336,7 +22363,7 @@ function cancelVnextRun(context, runId, options = {}) {
22336
22363
  abortControllers.push(owned.controller);
22337
22364
  }
22338
22365
  } else if (folded.status === "blocked_uncertain") {
22339
- push("run.status_changed", { status: "cancelling", reason: "operator_cancel" });
22366
+ push("run.status_changed", { status: "cancelling", reason: cancelReason });
22340
22367
  const attemptId = folded.currentStep?.attemptId;
22341
22368
  if (attemptId) {
22342
22369
  const capability = context.eventStore.capabilityByAttempt(attemptId);
@@ -22348,13 +22375,13 @@ function cancelVnextRun(context, runId, options = {}) {
22348
22375
  for (const owned of vnextAttemptControllers(context.eventStore.path, runId)) {
22349
22376
  abortControllers.push(owned.controller);
22350
22377
  }
22351
- push("run.status_changed", { status: "cancelled", reason: "operator_cancel" });
22378
+ push("run.status_changed", { status: "cancelled", reason: cancelReason });
22352
22379
  status = "cancelled";
22353
22380
  } else if (folded.status === "running" && !activeAttempt) {
22354
- push("run.status_changed", { status: "cancelling", reason: "operator_cancel" });
22355
- push("run.status_changed", { status: "cancelled", reason: "operator_cancel" });
22381
+ push("run.status_changed", { status: "cancelling", reason: cancelReason });
22382
+ push("run.status_changed", { status: "cancelled", reason: cancelReason });
22356
22383
  } else {
22357
- push("run.status_changed", { status: "cancelled", reason: "operator_cancel" });
22384
+ push("run.status_changed", { status: "cancelled", reason: cancelReason });
22358
22385
  }
22359
22386
  for (const event of events) context.eventStore.appendEvent(event);
22360
22387
  const nextState = foldStoredVnextRun(context, run);
@@ -24271,12 +24298,77 @@ async function driveAdmitted(context, runId, producer, token, options = {}) {
24271
24298
  }
24272
24299
  return latest;
24273
24300
  }
24301
+ function newDriveId(runId, token, runtimeId, monotonicNs) {
24302
+ return `drv_${createHash11("sha256").update(`${runId}\0${token}\0${runtimeId}\0${monotonicNs}`, "utf8").digest("hex").slice(0, 24)}`;
24303
+ }
24304
+ function inflightAttemptId(state) {
24305
+ const leftover = unreconciledPanelAttemptId(state);
24306
+ if (leftover) return leftover;
24307
+ if (state.currentStep?.attemptId) {
24308
+ const located = vnextFoldPanelAttempt(state.currentStep, state.currentStep.attemptId);
24309
+ const status = located?.attempt.status;
24310
+ if (status === "starting" || status === "executing" || status === "settling") return state.currentStep.attemptId;
24311
+ }
24312
+ return void 0;
24313
+ }
24314
+ function recordExecutingUnrecordedFailure(context, runId, attemptId, stepId) {
24315
+ context.eventStore.transaction(() => {
24316
+ const run = requireRun(context, runId);
24317
+ const now = (/* @__PURE__ */ new Date()).toISOString();
24318
+ const sequence = context.eventStore.nextSequence(runId);
24319
+ const event = {
24320
+ ...vnextEventBase(context, run, now, vnextMonotonicNs()),
24321
+ eventId: newVnextEventId(),
24322
+ eventType: "run.status_changed",
24323
+ sequence,
24324
+ payload: { status: "failed", reason: "executing_unrecorded", stepId }
24325
+ };
24326
+ context.eventStore.appendEvent(event);
24327
+ context.eventStore.settleCapability(attemptId, "revoked");
24328
+ const next = foldStoredVnextRun(context, run);
24329
+ persistVnextRunState(context, runId, next, sequence);
24330
+ context.eventStore.updateRunStatus(runId, "failed", now);
24331
+ });
24332
+ }
24333
+ function recordBareDriveFailure(context, runId) {
24334
+ if (isVnextRuntimeContextClosed(context)) return;
24335
+ try {
24336
+ const run = context.eventStore.run(runId);
24337
+ if (!run) return;
24338
+ const state = foldStoredVnextRun(context, run);
24339
+ if (isTerminalRunStatus(state.status) || state.status === "cancelling") return;
24340
+ const inflight = inflightAttemptId(state);
24341
+ if (inflight) {
24342
+ const currentStep = state.currentStep;
24343
+ const located = vnextFoldPanelAttempt(currentStep, inflight);
24344
+ if (currentStep && currentStep.panel.order.length === 1 && located?.attempt.status === "starting") {
24345
+ const plan = rehydrateVnextCompiledPlanFromStore(context.eventStore, run);
24346
+ const step = plan.steps[currentStep.stepId];
24347
+ if (step?.kind === "gate") return;
24348
+ if (step && (step.kind === "agent" || step.kind === "moa") && step.assignments.maximum > 1) return;
24349
+ recordExecutingUnrecordedFailure(context, runId, inflight, currentStep.stepId);
24350
+ }
24351
+ return;
24352
+ }
24353
+ cancelVnextRun(context, runId, { reason: "drive_error" });
24354
+ } catch {
24355
+ }
24356
+ }
24357
+ async function closeDriveProducer(producer) {
24358
+ if (typeof producer.close !== "function") return;
24359
+ try {
24360
+ await producer.close();
24361
+ } catch {
24362
+ }
24363
+ }
24274
24364
  var VnextRunScheduler = class _VnextRunScheduler {
24275
24365
  context;
24366
+ bundle;
24276
24367
  configRevision;
24277
- constructor(context, configRevision) {
24368
+ constructor(context, bundle) {
24278
24369
  this.context = context;
24279
- this.configRevision = configRevision;
24370
+ this.bundle = bundle;
24371
+ this.configRevision = bundle.configRevision;
24280
24372
  }
24281
24373
  static for(context, bundle) {
24282
24374
  if (String(bundle.project.value.id) !== context.projectId) {
@@ -24284,7 +24376,7 @@ var VnextRunScheduler = class _VnextRunScheduler {
24284
24376
  }
24285
24377
  const limits = vnextProjectAdmissionLimits(bundle);
24286
24378
  bindVnextSchedulerPolicy(context.eventStore.path, limits.maxConcurrentRuns, bundle.configRevision);
24287
- return new _VnextRunScheduler(context, bundle.configRevision);
24379
+ return new _VnextRunScheduler(context, bundle);
24288
24380
  }
24289
24381
  enqueue(runId, producer, options = {}) {
24290
24382
  requireTrustedProducer(producer);
@@ -24306,6 +24398,91 @@ var VnextRunScheduler = class _VnextRunScheduler {
24306
24398
  return Promise.reject(error);
24307
24399
  }
24308
24400
  }
24401
+ openDriveSession(runId, options) {
24402
+ const policy = vnextSchedulerPolicy(this.context.eventStore.path);
24403
+ if (!policy || policy.configRevision !== this.configRevision) {
24404
+ return Promise.reject(runtimeError("scheduler_policy_conflict", runId, "scheduler handle does not match the active policy"));
24405
+ }
24406
+ try {
24407
+ const run = requireRun(this.context, runId);
24408
+ if (isTerminalRunStatus(run.status) || run.status === "cancelling") {
24409
+ return Promise.reject(runtimeError("run_busy", runId, `run ${runId} is already ${run.status}`));
24410
+ }
24411
+ } catch (error) {
24412
+ return Promise.reject(error);
24413
+ }
24414
+ const limits = vnextProjectAdmissionLimits(this.bundle);
24415
+ const driveOptions = {
24416
+ liveMode: options.liveMode ?? options.mode === "live"
24417
+ };
24418
+ if (options.allowLimits !== void 0) driveOptions.allowLimits = options.allowLimits;
24419
+ let opened = false;
24420
+ const pending = {
24421
+ resolve: (_value) => void 0,
24422
+ reject: (_error) => void 0
24423
+ };
24424
+ const settled = new Promise((resolve9, reject) => {
24425
+ pending.resolve = resolve9;
24426
+ pending.reject = reject;
24427
+ });
24428
+ void settled.then(void 0, () => void 0);
24429
+ return new Promise((resolveOpen, rejectOpen) => {
24430
+ const queued = enqueueVnextScheduledRun(
24431
+ this.context.eventStore.path,
24432
+ runId,
24433
+ this.configRevision,
24434
+ limits.maxConcurrentRuns,
24435
+ async (token) => {
24436
+ let producer;
24437
+ try {
24438
+ producer = options.createProducer();
24439
+ requireTrustedProducer(producer);
24440
+ const current = requireRun(this.context, runId);
24441
+ if (current.status === "created") {
24442
+ pinVnextCompiledPlan(this.context, this.bundle, runId);
24443
+ }
24444
+ const started = startVnextRun(this.context, runId, driveOptions);
24445
+ if (started.handoff) {
24446
+ const error = runtimeError("run_handoff_required", runId, started.handoff.detail);
24447
+ Object.assign(error, { handoff: started.handoff });
24448
+ throw error;
24449
+ }
24450
+ const driveId = newDriveId(runId, token, this.context.homeRuntimeId, vnextMonotonicNs());
24451
+ const session = {
24452
+ driveId,
24453
+ runId,
24454
+ token,
24455
+ homeRuntimeId: this.context.homeRuntimeId,
24456
+ mode: options.mode,
24457
+ openedAt: (/* @__PURE__ */ new Date()).toISOString(),
24458
+ controller: new AbortController(),
24459
+ settled
24460
+ };
24461
+ attachVnextDriveSession(this.context.eventStore.path, runId, token, session);
24462
+ opened = true;
24463
+ resolveOpen({ driveId, settled });
24464
+ try {
24465
+ const result = await driveAdmitted(this.context, runId, producer, token, driveOptions);
24466
+ pending.resolve(result);
24467
+ return result;
24468
+ } catch (error) {
24469
+ recordBareDriveFailure(this.context, runId);
24470
+ pending.reject(error);
24471
+ throw error;
24472
+ }
24473
+ } finally {
24474
+ if (producer) await closeDriveProducer(producer);
24475
+ clearVnextDriveSession(this.context.eventStore.path, runId, token);
24476
+ }
24477
+ }
24478
+ );
24479
+ void queued.then(void 0, (error) => {
24480
+ if (!opened) {
24481
+ rejectOpen(error);
24482
+ }
24483
+ });
24484
+ });
24485
+ }
24309
24486
  };
24310
24487
  function invokeProducer(producer, request) {
24311
24488
  let pending;
@@ -24644,6 +24821,9 @@ function prepareDispatch(context, runId, producerId) {
24644
24821
  const run = requireRun(context, runId);
24645
24822
  const plan = rehydrateVnextCompiledPlanFromStore(context.eventStore, run);
24646
24823
  const state = foldStoredVnextRun(context, run);
24824
+ if (vnextPanelDispatchSeams.skipDispatch?.()) {
24825
+ return { kind: "return", state };
24826
+ }
24647
24827
  if (state.status === "cancelling" && vnextAttemptControllers(context.eventStore.path, runId).length === 0) {
24648
24828
  return {
24649
24829
  kind: "return",
@@ -26501,6 +26681,36 @@ function sendJson(response, status, payload) {
26501
26681
  response.writeHead(status, { "content-type": "application/json", "content-length": Buffer.byteLength(body) });
26502
26682
  response.end(body);
26503
26683
  }
26684
+ var DEFAULT_RUNTIME_STOP_GRACE_MS = 3e4;
26685
+ var MAX_RUNTIME_STOP_GRACE_MS = 6e5;
26686
+ function runtimeStopGraceMs(env = process.env) {
26687
+ const raw = env.KXM_RUNTIME_STOP_GRACE_MS;
26688
+ if (raw === void 0 || raw.trim() === "") return DEFAULT_RUNTIME_STOP_GRACE_MS;
26689
+ const parsed = Number(raw.trim());
26690
+ if (!Number.isFinite(parsed) || !Number.isInteger(parsed) || parsed < 0 || parsed > MAX_RUNTIME_STOP_GRACE_MS) {
26691
+ process.stderr.write(
26692
+ `KXM_RUNTIME_STOP_GRACE_MS must be an integer between 0 and ${MAX_RUNTIME_STOP_GRACE_MS} ms (10 minutes); using default ${DEFAULT_RUNTIME_STOP_GRACE_MS}
26693
+ `
26694
+ );
26695
+ return DEFAULT_RUNTIME_STOP_GRACE_MS;
26696
+ }
26697
+ return parsed;
26698
+ }
26699
+ async function waitForDriveSessions(settled, graceMs) {
26700
+ if (settled.length === 0) return;
26701
+ let timeout;
26702
+ try {
26703
+ await Promise.race([
26704
+ Promise.allSettled(settled),
26705
+ new Promise((resolve9) => {
26706
+ timeout = setTimeout(resolve9, graceMs);
26707
+ timeout.unref?.();
26708
+ })
26709
+ ]);
26710
+ } finally {
26711
+ if (timeout !== void 0) clearTimeout(timeout);
26712
+ }
26713
+ }
26504
26714
  async function startVnextRuntimeSupervisor(options = {}) {
26505
26715
  const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
26506
26716
  const paths = vnextRuntimePaths(options.stateRoot !== void 0 ? { stateRoot: options.stateRoot } : {});
@@ -26522,7 +26732,6 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
26522
26732
  const runtimeId = `rtm_${createHash12("sha256").update(`${paths.stateRoot}\0${process.pid}\0${now()}\0${randomBytes3(16).toString("hex")}`, "utf8").digest("hex").slice(0, 24)}`;
26523
26733
  const requestedPort = requestedPortOption ?? 0;
26524
26734
  let activeRuntimeId = runtimeId;
26525
- const activeDrives = /* @__PURE__ */ new Map();
26526
26735
  const contexts = /* @__PURE__ */ new Map();
26527
26736
  const contextFor = (projectRoot) => {
26528
26737
  if (!isAbsolute4(projectRoot)) {
@@ -26616,34 +26825,8 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
26616
26825
  }
26617
26826
  const run = context.eventStore.run(runId);
26618
26827
  if (!run) throw runtimeError("run_unknown", runId, "run not found");
26619
- if (activeDrives.has(runId)) {
26620
- sendJson(response, 409, { ok: false, error: "run_busy", message: `run ${runId} is already executing` });
26621
- return;
26622
- }
26623
- if (run.status === "completed" || run.status === "failed" || run.status === "cancelled" || run.status === "cancelling") {
26624
- sendJson(response, 409, { ok: false, error: "run_busy", message: `run ${runId} is already ${run.status}` });
26625
- return;
26626
- }
26627
- let releaseActive = () => {
26628
- };
26629
- const activePromise = new Promise((resolve9) => {
26630
- releaseActive = resolve9;
26631
- });
26632
- activeDrives.set(runId, activePromise);
26633
- const cleanupActive = () => {
26634
- activeDrives.delete(runId);
26635
- releaseActive();
26636
- };
26637
- if (run.status === "created") {
26638
- pinVnextCompiledPlan(context, bundle, runId);
26639
- const plan = startVnextRun(context, runId, { allowLimits: true });
26640
- if (plan.handoff) {
26641
- cleanupActive();
26642
- sendJson(response, 409, { ok: false, error: "run_handoff_required", handoff: plan.handoff });
26643
- return;
26644
- }
26645
- }
26646
- const producer = body.mode === "live" ? createVnextOneShotProducer({
26828
+ const delayMs = typeof body.delayMs === "number" && body.delayMs > 0 ? body.delayMs : 0;
26829
+ const createProducer = () => body.mode === "live" ? createVnextOneShotProducer({
26647
26830
  projectRoot,
26648
26831
  defaultHarness: String(bundle.project.value.defaultHarness ?? "pi"),
26649
26832
  resolveHarness: (agentId) => {
@@ -26662,56 +26845,50 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
26662
26845
  }
26663
26846
  return { provider, model: modelName };
26664
26847
  }
26665
- }) : (() => {
26666
- const delayMs = typeof body.delayMs === "number" && body.delayMs > 0 ? body.delayMs : 0;
26667
- return createVnextSimulatedProducer(async () => {
26668
- if (delayMs > 0) {
26669
- await new Promise((r) => setTimeout(r, delayMs));
26670
- }
26671
- return { outcome: "passed" };
26672
- });
26673
- })();
26674
- let drivePromise;
26848
+ }) : createVnextSimulatedProducer(async () => {
26849
+ if (delayMs > 0) {
26850
+ await new Promise((r) => setTimeout(r, delayMs));
26851
+ }
26852
+ return { outcome: "passed" };
26853
+ });
26854
+ let session;
26675
26855
  let earlyError;
26676
26856
  try {
26677
26857
  const scheduler = VnextRunScheduler.for(context, bundle);
26678
- drivePromise = scheduler.enqueue(runId, producer, { allowLimits: true, liveMode: body.mode === "live" });
26679
- drivePromise.catch((err) => {
26858
+ const opening = scheduler.openDriveSession(runId, {
26859
+ mode: body.mode,
26860
+ allowLimits: true,
26861
+ liveMode: body.mode === "live",
26862
+ createProducer
26863
+ });
26864
+ opening.catch((err) => {
26680
26865
  earlyError = err;
26681
26866
  });
26867
+ session = await opening;
26682
26868
  } catch (err) {
26683
26869
  earlyError = err;
26684
26870
  }
26685
- await Promise.resolve();
26686
26871
  if (earlyError) {
26687
- cleanupActive();
26688
26872
  const errStr = String(earlyError);
26873
+ if (errStr.includes("run_handoff_required")) {
26874
+ const handoff = earlyError.handoff;
26875
+ sendJson(response, 409, { ok: false, error: "run_handoff_required", ...handoff !== void 0 ? { handoff } : {} });
26876
+ return;
26877
+ }
26689
26878
  if (errStr.includes("run_busy") || errStr.includes("scheduler_policy_conflict")) {
26690
- if ("close" in producer && typeof producer.close === "function") {
26691
- try {
26692
- await producer.close();
26693
- } catch {
26694
- }
26695
- }
26696
26879
  sendJson(response, 409, { ok: false, error: "run_busy", message: `run ${runId} is already admitted or queued` });
26697
26880
  return;
26698
26881
  }
26699
26882
  throw earlyError;
26700
26883
  }
26701
- void drivePromise.finally(async () => {
26702
- cleanupActive();
26703
- if ("close" in producer && typeof producer.close === "function") {
26704
- try {
26705
- await producer.close();
26706
- } catch {
26707
- }
26708
- }
26709
- }).catch(() => {
26884
+ void session.settled.catch(() => {
26710
26885
  });
26886
+ if (response.writableEnded) return;
26711
26887
  sendJson(response, 202, {
26712
26888
  ok: true,
26713
26889
  status: "accepted",
26714
26890
  runId,
26891
+ driveId: session.driveId,
26715
26892
  poll: `/v1/runs/${runId}`,
26716
26893
  mode: body.mode
26717
26894
  });
@@ -26842,9 +27019,18 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
26842
27019
  registry.markStopping(process.pid, now());
26843
27020
  } catch {
26844
27021
  }
26845
- if (activeDrives.size > 0) {
26846
- await Promise.allSettled([...activeDrives.values()]);
27022
+ const openSessions = [...contexts.values()].flatMap((context) => vnextOpenDriveSessions(context.eventStore.path).map((session) => ({ context, session })));
27023
+ for (const { context, session } of openSessions) {
27024
+ try {
27025
+ cancelVnextRun(context, session.runId, { reason: "runtime_shutdown" });
27026
+ } catch {
27027
+ }
27028
+ try {
27029
+ session.controller.abort();
27030
+ } catch {
27031
+ }
26847
27032
  }
27033
+ await waitForDriveSessions(openSessions.map(({ session }) => session.settled), runtimeStopGraceMs());
26848
27034
  for (const context of contexts.values()) closeVnextRuntimeContext(context);
26849
27035
  contexts.clear();
26850
27036
  const closed = new Promise((resolveStop) => server.close(() => resolveStop()));
@@ -29167,11 +29353,13 @@ export {
29167
29353
  DEFAULT_LOG_MAX_BYTES,
29168
29354
  DEFAULT_LOG_MAX_FILES,
29169
29355
  DEFAULT_MODES_CONFIG,
29356
+ DEFAULT_RUNTIME_STOP_GRACE_MS,
29170
29357
  DEFAULT_SOCKET_DIR,
29171
29358
  DEFAULT_SUBAGENT_MODELS,
29172
29359
  IMPROVEMENT_REPORT_SCHEMA,
29173
29360
  IMPROVEMENT_REPORT_V1_SCHEMA,
29174
29361
  LOG_LEVEL_PRIORITY,
29362
+ MAX_RUNTIME_STOP_GRACE_MS,
29175
29363
  MAX_SSH_OUTPUT_BYTES,
29176
29364
  MAX_SSH_OUTPUT_LINES,
29177
29365
  NATIVE_HARNESS_PROVIDERS,
@@ -29289,6 +29477,7 @@ export {
29289
29477
  rotateLogFiles,
29290
29478
  runHarnessUpdate,
29291
29479
  runtimeError,
29480
+ runtimeStopGraceMs,
29292
29481
  sanitizeLogOutput,
29293
29482
  startVnextRuntimeSupervisor,
29294
29483
  tableColumns,