@adhdev/daemon-standalone 1.0.45-rc.5 → 1.0.45-rc.7

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/dist/index.js CHANGED
@@ -36227,6 +36227,7 @@ var require_dist3 = __commonJS({
36227
36227
  function normalizeMeshSchedulingStrategy(value) {
36228
36228
  if (typeof value !== "string") return DEFAULT_MESH_SCHEDULING_STRATEGY;
36229
36229
  const trimmed = value.trim();
36230
+ if (trimmed === "least_loaded" || trimmed === "round_robin") return "fitness";
36230
36231
  return MESH_SCHEDULING_STRATEGIES.includes(trimmed) ? trimmed : DEFAULT_MESH_SCHEDULING_STRATEGY;
36231
36232
  }
36232
36233
  function resolveNodeSchedulingPriority(nodePolicy) {
@@ -36239,12 +36240,14 @@ var require_dist3 = __commonJS({
36239
36240
  function resolveQuotaRoutingPolicy(value) {
36240
36241
  const staleAfterMs = Number(value?.staleAfterMs);
36241
36242
  const sessionMin = Number(value?.sessionMinRemainingPercent);
36243
+ const sessionResetImminentMs = Number(value?.sessionResetImminentMs);
36242
36244
  const weeklyMin = Number(value?.weeklyMinRemainingPercent);
36243
36245
  const spreadMax = Number(value?.spreadBonusMax);
36244
36246
  const clampPercentField = (n, fallback) => Number.isFinite(n) ? Math.min(100, Math.max(0, n)) : fallback;
36245
36247
  return {
36246
36248
  staleAfterMs: Number.isFinite(staleAfterMs) && staleAfterMs >= 0 ? Math.floor(staleAfterMs) : DEFAULT_QUOTA_ROUTING_POLICY.staleAfterMs,
36247
36249
  sessionMinRemainingPercent: clampPercentField(sessionMin, DEFAULT_QUOTA_ROUTING_POLICY.sessionMinRemainingPercent),
36250
+ sessionResetImminentMs: Number.isFinite(sessionResetImminentMs) && sessionResetImminentMs >= 0 ? Math.floor(sessionResetImminentMs) : DEFAULT_QUOTA_ROUTING_POLICY.sessionResetImminentMs,
36248
36251
  weeklyMinRemainingPercent: clampPercentField(weeklyMin, DEFAULT_QUOTA_ROUTING_POLICY.weeklyMinRemainingPercent),
36249
36252
  spreadBonusMax: Number.isFinite(spreadMax) && spreadMax >= 0 ? spreadMax : DEFAULT_QUOTA_ROUTING_POLICY.spreadBonusMax
36250
36253
  };
@@ -36260,6 +36263,9 @@ var require_dist3 = __commonJS({
36260
36263
  if (record2.sessionMinRemainingPercent !== void 0 && resolved.sessionMinRemainingPercent !== DEFAULT_QUOTA_ROUTING_POLICY.sessionMinRemainingPercent) {
36261
36264
  out.sessionMinRemainingPercent = resolved.sessionMinRemainingPercent;
36262
36265
  }
36266
+ if (record2.sessionResetImminentMs !== void 0 && resolved.sessionResetImminentMs !== DEFAULT_QUOTA_ROUTING_POLICY.sessionResetImminentMs) {
36267
+ out.sessionResetImminentMs = resolved.sessionResetImminentMs;
36268
+ }
36263
36269
  if (record2.weeklyMinRemainingPercent !== void 0 && resolved.weeklyMinRemainingPercent !== DEFAULT_QUOTA_ROUTING_POLICY.weeklyMinRemainingPercent) {
36264
36270
  out.weeklyMinRemainingPercent = resolved.weeklyMinRemainingPercent;
36265
36271
  }
@@ -36499,6 +36505,7 @@ var require_dist3 = __commonJS({
36499
36505
  DEFAULT_QUOTA_ROUTING_POLICY = {
36500
36506
  staleAfterMs: 30 * 60 * 1e3,
36501
36507
  sessionMinRemainingPercent: 10,
36508
+ sessionResetImminentMs: 5 * 60 * 1e3,
36502
36509
  weeklyMinRemainingPercent: 15,
36503
36510
  spreadBonusMax: 30
36504
36511
  };
@@ -37020,10 +37027,10 @@ var require_dist3 = __commonJS({
37020
37027
  }
37021
37028
  function getDaemonBuildInfo() {
37022
37029
  if (cached2) return cached2;
37023
- const commit = readInjected(true ? "fc7a3adae844e18bc983aeb8089edad7ff38d116" : void 0) ?? "unknown";
37024
- const commitShort = readInjected(true ? "fc7a3ada" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
37025
- const version2 = readInjected(true ? "1.0.45-rc.5" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
37026
- const builtAt = readInjected(true ? "2026-08-12T03:20:09.297Z" : void 0);
37030
+ const commit = readInjected(true ? "c935da6be0da24d1e046a4ecb5139e8490dba7b4" : void 0) ?? "unknown";
37031
+ const commitShort = readInjected(true ? "c935da6b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
37032
+ const version2 = readInjected(true ? "1.0.45-rc.7" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
37033
+ const builtAt = readInjected(true ? "2026-08-12T10:49:30.678Z" : void 0);
37027
37034
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
37028
37035
  return cached2;
37029
37036
  }
@@ -42162,6 +42169,7 @@ ${error48.message || ""}`;
42162
42169
  buildSlotProposal: () => buildSlotProposal,
42163
42170
  canonicalDaemonId: () => canonicalDaemonId,
42164
42171
  daemonIdsEquivalent: () => daemonIdsEquivalent,
42172
+ deriveProviderPriorityFromSlots: () => deriveProviderPriorityFromSlots,
42165
42173
  deriveSlotsFromLegacy: () => deriveSlotsFromLegacy,
42166
42174
  expandDaemonIdForms: () => expandDaemonIdForms,
42167
42175
  formatQuotaAccount: () => formatQuotaAccount,
@@ -42626,6 +42634,16 @@ ${error48.message || ""}`;
42626
42634
  };
42627
42635
  });
42628
42636
  }
42637
+ function deriveProviderPriorityFromSlots(slots) {
42638
+ const seen = /* @__PURE__ */ new Set();
42639
+ const out = [];
42640
+ for (const slot of normalizeNodeCapabilitySlots(slots)) {
42641
+ if (seen.has(slot.provider)) continue;
42642
+ seen.add(slot.provider);
42643
+ out.push(slot.provider);
42644
+ }
42645
+ return out;
42646
+ }
42629
42647
  function slotKey(slot) {
42630
42648
  return [
42631
42649
  slot.provider,
@@ -48572,11 +48590,12 @@ Next step: ${nextStep}`;
48572
48590
  ON mesh_missions(mesh_id, status, updated_at);
48573
48591
 
48574
48592
  -- Load-balancing scheduler: per-mesh round-robin rotation cursor. When
48575
- -- the schedulingStrategy is 'round_robin', several eligible nodes tied at
48576
- -- the least load are rotated by this cursor so the tie-break winner cycles
48577
- -- across scheduling passes instead of always favouring the same array-order
48578
- -- node. Persisted (not a module Map) so rotation survives daemon restarts
48579
- -- and stays a single source of truth across scheduling entry points.
48593
+ -- the schedulingStrategy spreads work ('fitness' with no task in scope),
48594
+ -- eligible nodes tied at the same (priority, load) are rotated by this
48595
+ -- cursor so the tie-break winner cycles across scheduling passes instead
48596
+ -- of always favouring the same array-order node. Persisted (not a module
48597
+ -- Map) so rotation survives daemon restarts and stays a single source of
48598
+ -- truth across scheduling entry points.
48580
48599
  CREATE TABLE IF NOT EXISTS mesh_scheduler_cursor (
48581
48600
  mesh_id TEXT PRIMARY KEY,
48582
48601
  cursor INTEGER NOT NULL DEFAULT 0
@@ -55243,13 +55262,16 @@ ${rendered}`, "utf-8");
55243
55262
  function readProviderPriorityFromPolicy(policy) {
55244
55263
  const record2 = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
55245
55264
  const raw = record2.providerPriority;
55246
- if (!Array.isArray(raw)) return [];
55247
- const seen = /* @__PURE__ */ new Set();
55248
- return raw.map((type2) => typeof type2 === "string" ? type2.trim() : "").filter(Boolean).filter((type2) => {
55249
- if (seen.has(type2)) return false;
55250
- seen.add(type2);
55251
- return true;
55252
- });
55265
+ if (Array.isArray(raw)) {
55266
+ const seen = /* @__PURE__ */ new Set();
55267
+ const explicit = raw.map((type2) => typeof type2 === "string" ? type2.trim() : "").filter(Boolean).filter((type2) => {
55268
+ if (seen.has(type2)) return false;
55269
+ seen.add(type2);
55270
+ return true;
55271
+ });
55272
+ if (explicit.length) return explicit;
55273
+ }
55274
+ return deriveProviderPriorityFromSlots(record2.slots);
55253
55275
  }
55254
55276
  function normalizeProviderRoles(value) {
55255
55277
  if (!Array.isArray(value)) return [];
@@ -60480,6 +60502,14 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
60480
60502
  if (!Number.isFinite(used)) return void 0;
60481
60503
  return Math.min(100, Math.max(0, 100 - used));
60482
60504
  }
60505
+ function isSessionResetImminent(session, facts, quota, imminentMs, now) {
60506
+ const resetsAt = Number(session?.resetsAt);
60507
+ if (!Number.isFinite(resetsAt) || resetsAt <= 0) return false;
60508
+ const ageMs2 = quotaSnapshotAgeMs(facts, quota, now);
60509
+ if (!Number.isFinite(ageMs2)) return false;
60510
+ const reporterNowMs = Number(quota.updatedAt) + ageMs2;
60511
+ return resetsAt - reporterNowMs < imminentMs;
60512
+ }
60483
60513
  function evaluateProviderQuotaGate(node, providerType, policy, now = Date.now()) {
60484
60514
  const entry = quotaEntryFor(node, providerType);
60485
60515
  if (!entry) return null;
@@ -60488,7 +60518,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
60488
60518
  if (!isQuotaSnapshotFresh(facts, quota, policy, now)) return null;
60489
60519
  const resolved = resolveQuotaRoutingPolicy(policy);
60490
60520
  const session = remainingPercent(quota.session);
60491
- if (session !== void 0 && session < resolved.sessionMinRemainingPercent) {
60521
+ if (session !== void 0 && session < resolved.sessionMinRemainingPercent && !isSessionResetImminent(quota.session, facts, quota, resolved.sessionResetImminentMs, now)) {
60492
60522
  return {
60493
60523
  reason: PROVIDER_QUOTA_SESSION_LOW_SKIP_REASON,
60494
60524
  window: "session",
@@ -61228,7 +61258,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
61228
61258
  }
61229
61259
  const priorityOf = (n) => resolveNodeSchedulingPriority(n.node?.policy);
61230
61260
  let rotation = 0;
61231
- if (strategy === "least_loaded" || strategy === "round_robin") {
61261
+ if (strategy === "fitness") {
61232
61262
  const cursor = opts?.bumpCursor ? MeshRuntimeStore.getInstance().bumpSchedulerCursor(meshId) : MeshRuntimeStore.getInstance().getSchedulerCursor(meshId);
61233
61263
  rotation = (cursor % nodes.length + nodes.length) % nodes.length;
61234
61264
  }
@@ -61236,7 +61266,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
61236
61266
  return [...nodes].sort((a, b) => {
61237
61267
  const prioDelta = priorityOf(b) - priorityOf(a);
61238
61268
  if (prioDelta !== 0) return prioDelta;
61239
- if (strategy === "least_loaded" || strategy === "round_robin") {
61269
+ if (strategy === "fitness") {
61240
61270
  const loadDelta = nodeActiveLoad(meshId, a.nodeId) - nodeActiveLoad(meshId, b.nodeId);
61241
61271
  if (loadDelta !== 0) return loadDelta;
61242
61272
  }
@@ -61610,6 +61640,11 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
61610
61640
  LOG2.info("MeshQueue", `Deferring queue claim for node ${nodeId} (${sessionId}): an auto fast-forward is mutating its workspace \u2014 task left pending, claim re-fires next tick`);
61611
61641
  return false;
61612
61642
  }
61643
+ const quotaClaimBlock = evaluateProviderQuotaGate(node, providerType, mesh?.policy?.quotaRouting ?? null);
61644
+ if (quotaClaimBlock) {
61645
+ LOG2.info("MeshQueue", `QUOTA GATE: deferring queue claim for node ${nodeId} (${sessionId}): provider '${providerType}' has ${quotaClaimBlock.remainingPercent.toFixed(1)}% ${quotaClaimBlock.window} quota remaining (< ${quotaClaimBlock.thresholdPercent}% threshold) \u2014 task left pending until the window resets`);
61646
+ return false;
61647
+ }
61613
61648
  const inlineBootstrapNode = (() => {
61614
61649
  try {
61615
61650
  const inlineMesh = components.router?.getCachedInlineMesh?.(meshId);
@@ -62604,7 +62639,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
62604
62639
  const aPrio = resolveNodeSchedulingPriority(a.node?.policy);
62605
62640
  const bPrio = resolveNodeSchedulingPriority(b.node?.policy);
62606
62641
  if (aPrio !== bPrio) return bPrio - aPrio;
62607
- if (strategy === "least_loaded" || strategy === "round_robin" || strategy === "fitness") {
62642
+ if (strategy === "fitness") {
62608
62643
  const loadDelta = nodeActiveLoad(meshId, a.nodeId) - nodeActiveLoad(meshId, b.nodeId);
62609
62644
  if (loadDelta !== 0) return loadDelta;
62610
62645
  }
@@ -72410,7 +72445,109 @@ ${cleanBody}`;
72410
72445
  if (!event || typeof event !== "object") return null;
72411
72446
  return event;
72412
72447
  }
72448
+ function parseSelectorRow(line) {
72449
+ const m = line.match(/^\s*(?:❯\s*)?(\S[\s\S]*?)\s*$/);
72450
+ if (!m) return null;
72451
+ const parts = m[1].split(/\s{2,}/);
72452
+ const label = (parts[0] ?? "").trim();
72453
+ if (!label) return null;
72454
+ const description = parts.length > 1 ? parts.slice(1).join(" ").trim() : void 0;
72455
+ return { label, ...description ? { description } : {} };
72456
+ }
72457
+ function detectKimiIdleSelectorPrompt(screenText) {
72458
+ if (!screenText) return null;
72459
+ const lines = screenText.split("\n");
72460
+ let titleIdx = -1;
72461
+ for (let i = lines.length - 1; i >= 0; i -= 1) {
72462
+ if (IDLE_SELECTOR_TITLE.test(lines[i])) {
72463
+ titleIdx = i;
72464
+ break;
72465
+ }
72466
+ }
72467
+ if (titleIdx < 0) return null;
72468
+ let hintIdx = -1;
72469
+ for (let i = titleIdx + 1; i <= Math.min(lines.length - 1, titleIdx + 4); i += 1) {
72470
+ if (IDLE_SELECTOR_HINT.test(lines[i])) {
72471
+ hintIdx = i;
72472
+ break;
72473
+ }
72474
+ }
72475
+ if (hintIdx < 0) return null;
72476
+ let cursorIdx = -1;
72477
+ for (let i = hintIdx + 1; i < lines.length; i += 1) {
72478
+ const t = lines[i].trim();
72479
+ if (!t) continue;
72480
+ if (/^─+$/.test(t)) break;
72481
+ if (t.startsWith("\u276F")) {
72482
+ cursorIdx = i;
72483
+ break;
72484
+ }
72485
+ }
72486
+ if (cursorIdx < 0) return null;
72487
+ const options = [];
72488
+ for (let i = cursorIdx; i < lines.length; i += 1) {
72489
+ const t = lines[i].trim();
72490
+ if (!t || /^─+$/.test(t)) break;
72491
+ const row = parseSelectorRow(lines[i]);
72492
+ if (!row) break;
72493
+ options.push(row);
72494
+ }
72495
+ if (options.length < 2) return null;
72496
+ let question = "";
72497
+ for (let i = cursorIdx - 1; i > hintIdx; i -= 1) {
72498
+ const t = lines[i].trim();
72499
+ if (!t || /^─+$/.test(t)) continue;
72500
+ question = t;
72501
+ break;
72502
+ }
72503
+ if (!question) return null;
72504
+ const questions = [{
72505
+ questionId: "q1",
72506
+ question,
72507
+ header: lines[titleIdx].trim(),
72508
+ multiSelect: false,
72509
+ options
72510
+ }];
72511
+ return {
72512
+ promptId: `${KIMI_TUI_SELECTOR_PROMPT_PREFIX}${interactivePromptContentFingerprint(questions)}`,
72513
+ origin: "cli",
72514
+ providerType: "kimi",
72515
+ createdAt: Date.now(),
72516
+ questions
72517
+ };
72518
+ }
72519
+ function buildKimiSelectorAnswerSteps(prompt, response, screenText) {
72520
+ if (response.promptId !== prompt.promptId) throw new Error("Interactive prompt response does not match active prompt");
72521
+ if (prompt.questions.length !== 1) throw new Error("kimi built-in selector prompt must have exactly one question");
72522
+ const question = prompt.questions[0];
72523
+ const answer = response.answers[question.questionId];
72524
+ if (!answer) throw new Error(`Missing answer for ${question.questionId}`);
72525
+ if (answer.freeformText?.trim()) throw new Error("kimi built-in selector has no freeform input");
72526
+ if (answer.selectedLabels.length !== 1) throw new Error(`Expected one selected label for ${question.questionId}`);
72527
+ const target = question.options.findIndex((o) => o.label === answer.selectedLabels[0]);
72528
+ if (target < 0) throw new Error(`Unknown option for ${question.questionId}: ${answer.selectedLabels[0]}`);
72529
+ let cursor = 0;
72530
+ for (const line of (screenText ?? "").split("\n")) {
72531
+ if (!line.trim().startsWith("\u276F")) continue;
72532
+ const row = parseSelectorRow(line);
72533
+ if (!row) continue;
72534
+ const idx = question.options.findIndex((o) => o.label === row.label);
72535
+ if (idx >= 0) {
72536
+ cursor = idx;
72537
+ break;
72538
+ }
72539
+ }
72540
+ const steps = [];
72541
+ const diff = target - cursor;
72542
+ const key2 = diff > 0 ? "\x1B[B" : "\x1B[A";
72543
+ for (let i = 0; i < Math.abs(diff); i += 1) steps.push(key2);
72544
+ steps.push("\r");
72545
+ return steps;
72546
+ }
72413
72547
  var TAIL_BYTES2;
72548
+ var KIMI_TUI_SELECTOR_PROMPT_PREFIX;
72549
+ var IDLE_SELECTOR_TITLE;
72550
+ var IDLE_SELECTOR_HINT;
72414
72551
  var init_kimi_pending_question = __esm2({
72415
72552
  "src/providers/kimi-pending-question.ts"() {
72416
72553
  "use strict";
@@ -72419,6 +72556,9 @@ ${cleanBody}`;
72419
72556
  init_background_task_detector();
72420
72557
  init_interactive_prompt();
72421
72558
  TAIL_BYTES2 = 512 * 1024;
72559
+ KIMI_TUI_SELECTOR_PROMPT_PREFIX = "kimi-tui-selector-";
72560
+ IDLE_SELECTOR_TITLE = /This session has been idle for/i;
72561
+ IDLE_SELECTOR_HINT = /↑↓\s*navigate\s*·\s*Enter\s+select/i;
72422
72562
  }
72423
72563
  });
72424
72564
  var pty_transport_exports = {};
@@ -75493,12 +75633,13 @@ ${cont}` : cont;
75493
75633
  // it. Reset to 0 the instant any poll is ineligible.
75494
75634
  staticIdlePollStreak = 0;
75495
75635
  /**
75496
- * kimi AskUserQuestion picker hold (wire.jsonl authority). kimi renders
75497
- * AskUserQuestion as a TUI picker the modal/spinner matchers do NOT
75498
- * classify, so the session reads 'generating' while parked on the
75499
- * question. Refreshed from the session's own wire.jsonl on each
75500
- * getScriptParsedStatus() poll (refreshKimiPendingQuestion — same
75501
- * cadence/rationale as the background-task passthrough), surfaced on
75636
+ * kimi interactive-picker hold. Covers (a) the AskUserQuestion picker
75637
+ * (wire.jsonl authority — kimi renders it as a TUI picker the modal/spinner
75638
+ * matchers do NOT classify, so the session reads 'generating' while parked)
75639
+ * and (b) kimi's built-in idle/cache-expired selector (screen authority —
75640
+ * a TUI built-in the wire never carries). Refreshed on each
75641
+ * getScriptParsedStatus()/getStatus() poll (refreshKimiPendingQuestion
75642
+ * same cadence/rationale as the background-task passthrough), surfaced on
75502
75643
  * getStatus() as activeInteractivePrompt so CliProviderInstance overlays
75503
75644
  * waiting_choice and the status-transition layer emits agent:waiting_choice,
75504
75645
  * and consumed by setInteractivePromptResponse (mesh_answer_question) to
@@ -76395,23 +76536,28 @@ ${lastSnapshot}`;
76395
76536
  */
76396
76537
  refreshKimiPendingQuestion() {
76397
76538
  if (this.cliType !== "kimi") return;
76398
- const nativeHistory = this.provider?.nativeHistory;
76399
- if (!nativeHistory?.source) return;
76400
76539
  try {
76401
- const prompt = detectKimiPendingQuestion(nativeHistory, {
76402
- agentType: this.cliType,
76403
- providerSessionId: this.providerSessionId || void 0,
76404
- sessionStartedAtMs: this.spawnAt,
76405
- envOverrides: this.extraEnv,
76406
- workspace: this.workingDir,
76407
- // Sidecar-claim owner token (== session registry sessionId ==
76408
- // the read path's targetSessionId). WITHOUT it claiming is
76409
- // skipped and the sidecar resolution fails closed on
76410
- // ambiguity any second kimi session dir in the workspace
76411
- // (e.g. a probe session) made detection silently dead
76412
- // (live: coordinator AskUserQuestion never surfaced).
76413
- instanceId: this.owningSessionId || void 0
76414
- });
76540
+ const nativeHistory = this.provider?.nativeHistory;
76541
+ let prompt = null;
76542
+ if (nativeHistory?.source) {
76543
+ prompt = detectKimiPendingQuestion(nativeHistory, {
76544
+ agentType: this.cliType,
76545
+ providerSessionId: this.providerSessionId || void 0,
76546
+ sessionStartedAtMs: this.spawnAt,
76547
+ envOverrides: this.extraEnv,
76548
+ workspace: this.workingDir,
76549
+ // Sidecar-claim owner token (== session registry sessionId ==
76550
+ // the read path's targetSessionId). WITHOUT it claiming is
76551
+ // skipped and the sidecar resolution fails closed on
76552
+ // ambiguity any second kimi session dir in the workspace
76553
+ // (e.g. a probe session) made detection silently dead
76554
+ // (live: coordinator AskUserQuestion never surfaced).
76555
+ instanceId: this.owningSessionId || void 0
76556
+ });
76557
+ }
76558
+ if (!prompt && this.engine.currentStatus !== "generating") {
76559
+ prompt = detectKimiIdleSelectorPrompt(this.terminalScreen.getText());
76560
+ }
76415
76561
  if ((prompt?.promptId ?? null) !== (this.activeInteractivePrompt?.promptId ?? null)) {
76416
76562
  this.activeInteractivePrompt = prompt;
76417
76563
  this.onStatusChange?.();
@@ -76471,7 +76617,7 @@ ${lastSnapshot}`;
76471
76617
  if (!prompt || prompt.promptId !== response.promptId) {
76472
76618
  throw new Error("Interactive prompt response does not match active prompt");
76473
76619
  }
76474
- const steps = buildKimiInteractiveTuiAnswerSteps(prompt, response);
76620
+ const steps = prompt.promptId.startsWith(KIMI_TUI_SELECTOR_PROMPT_PREFIX) ? buildKimiSelectorAnswerSteps(prompt, response, this.terminalScreen.getText()) : buildKimiInteractiveTuiAnswerSteps(prompt, response);
76475
76621
  for (const step of steps) {
76476
76622
  await this.writeToPty(step);
76477
76623
  await new Promise((resolve29) => setTimeout(resolve29, 180));
@@ -109213,6 +109359,10 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
109213
109359
  if (await isAncestor2(worktreeOssSha, sourceSha)) return "advance";
109214
109360
  return "skip_diverged";
109215
109361
  }
109362
+ function syncProviderPriorityFromSlots(policy, slots = policy.slots) {
109363
+ const derived = deriveProviderPriorityFromSlots(slots);
109364
+ if (derived.length) policy.providerPriority = derived;
109365
+ }
109216
109366
  async function syncClonedWorktreeSubmodules(worktreePath, sourceWorkspace, rg) {
109217
109367
  const submodulePaths = getRegisteredSubmodulePaths(worktreePath);
109218
109368
  if (submodulePaths.size === 0) return;
@@ -109776,12 +109926,15 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
109776
109926
  const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type2) => typeof type2 === "string" ? type2.trim() : "").filter(Boolean) : [];
109777
109927
  const readOnly = args?.readOnly === true;
109778
109928
  const providerRoles = normalizeProviderRoles(args?.providerRoles);
109929
+ const slots = normalizeNodeCapabilitySlots(args?.slots);
109779
109930
  const policy = {
109780
109931
  ...readOnly ? { readOnly: true } : {},
109781
109932
  ...providerPriority.length ? { providerPriority } : {},
109782
- ...providerRoles.length ? { providerRoles } : {}
109933
+ ...providerRoles.length ? { providerRoles } : {},
109934
+ ...slots.length ? { slots } : {}
109783
109935
  };
109784
109936
  if (providerRoles.length) migrateProviderRolesToSlots2(policy);
109937
+ if (!providerPriority.length) syncProviderPriorityFromSlots(policy);
109785
109938
  const role = normalizeMeshDaemonRole(args?.role);
109786
109939
  const daemonId = typeof args?.daemonId === "string" && args.daemonId.trim() ? args.daemonId.trim() : void 0;
109787
109940
  const machineId = typeof args?.machineId === "string" && args.machineId.trim() ? args.machineId.trim() : void 0;
@@ -109816,7 +109969,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
109816
109969
  const ownerFailure = await ctx.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "node update");
109817
109970
  if (ownerFailure) return ownerFailure;
109818
109971
  try {
109819
- const { updateNode: updateNode2, normalizeCapabilityTags: normalizeCapabilityTags2, migrateProviderRolesToSlots: migrateProviderRolesToSlots2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
109972
+ const { updateNode: updateNode2, normalizeCapabilityTags: normalizeCapabilityTags2, migrateProviderRolesToSlots: migrateProviderRolesToSlots2, getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
109820
109973
  const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
109821
109974
  if (Array.isArray(args?.providerPriority)) {
109822
109975
  const providerPriority = args.providerPriority.map((type2) => typeof type2 === "string" ? type2.trim() : "").filter(Boolean);
@@ -109833,6 +109986,10 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
109833
109986
  else delete policy.providerRoles;
109834
109987
  }
109835
109988
  migrateProviderRolesToSlots2(policy);
109989
+ if (!Array.isArray(args?.providerPriority) && !Object.prototype.hasOwnProperty.call(policy, "providerPriority")) {
109990
+ const finalSlots = Object.prototype.hasOwnProperty.call(policy, "slots") ? policy.slots : getMesh2(meshId)?.nodes.find((n) => n.id === nodeId)?.policy?.slots;
109991
+ syncProviderPriorityFromSlots(policy, finalSlots);
109992
+ }
109836
109993
  const patch = { policy };
109837
109994
  if (typeof args?.systemPrompt === "string") {
109838
109995
  const trimmed = args.systemPrompt.trim();
@@ -109857,6 +110014,9 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
109857
110014
  ...inlineNode.policy && typeof inlineNode.policy === "object" && !Array.isArray(inlineNode.policy) ? inlineNode.policy : {},
109858
110015
  ...patch.policy
109859
110016
  };
110017
+ if (!Array.isArray(args?.providerPriority) && !Object.prototype.hasOwnProperty.call(patch.policy, "providerPriority")) {
110018
+ syncProviderPriorityFromSlots(inlineNode.policy);
110019
+ }
109860
110020
  if (Object.prototype.hasOwnProperty.call(patch, "systemPrompt")) {
109861
110021
  const sp = patch.systemPrompt;
109862
110022
  if (typeof sp === "string" && sp.trim()) inlineNode.systemPrompt = sp;