@adhdev/daemon-core 0.9.82-rc.483 → 0.9.82-rc.485

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
@@ -409,10 +409,10 @@ function readInjected(value) {
409
409
  }
410
410
  function getDaemonBuildInfo() {
411
411
  if (cached) return cached;
412
- const commit = readInjected(true ? "0862a3f10fa9de60a46591c0894a7209534db2e2" : void 0) ?? "unknown";
413
- const commitShort = readInjected(true ? "0862a3f1" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
- const version = readInjected(true ? "0.9.82-rc.483" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
- const builtAt = readInjected(true ? "2026-07-08T04:27:00.139Z" : void 0);
412
+ const commit = readInjected(true ? "ddf2eb6eafcf949165edfda2c3cf7c77597fa6f8" : void 0) ?? "unknown";
413
+ const commitShort = readInjected(true ? "ddf2eb6e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
+ const version = readInjected(true ? "0.9.82-rc.485" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
+ const builtAt = readInjected(true ? "2026-07-08T15:14:11.978Z" : void 0);
416
416
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
417
417
  return cached;
418
418
  }
@@ -2771,12 +2771,45 @@ function summarizeGitShape(status) {
2771
2771
  submodules
2772
2772
  };
2773
2773
  }
2774
- var DAEMON_ID_PREFIXES, MAGI_RAW_ANSWER_CAP, CANONICAL_MESH_TOOL_NAMES, CANONICAL_MESH_TOOL_COUNT;
2774
+ function isMeshTaskDifficulty(value) {
2775
+ return typeof value === "string" && MESH_TASK_DIFFICULTIES.includes(value);
2776
+ }
2777
+ function normalizeThinkingLevel(value) {
2778
+ const v = typeof value === "string" ? value.trim().toLowerCase() : "";
2779
+ return v === "low" || v === "medium" || v === "high" ? v : void 0;
2780
+ }
2781
+ function normalizeBrainSlot(raw) {
2782
+ const r = raw && typeof raw === "object" ? raw : {};
2783
+ const provider = typeof r.provider === "string" ? r.provider.trim() : "";
2784
+ const model = typeof r.model === "string" ? r.model.trim() : "";
2785
+ const thinkingLevel = normalizeThinkingLevel(r.thinkingLevel);
2786
+ return {
2787
+ ...provider ? { provider } : {},
2788
+ ...model ? { model } : {},
2789
+ ...thinkingLevel ? { thinkingLevel } : {}
2790
+ };
2791
+ }
2792
+ function normalizeDifficultyBrainMap(raw) {
2793
+ const out = {};
2794
+ if (!raw || typeof raw !== "object") return out;
2795
+ for (const key2 of MESH_TASK_DIFFICULTIES) {
2796
+ const slot = normalizeBrainSlot(raw[key2]);
2797
+ if (slot.provider || slot.model || slot.thinkingLevel) out[key2] = slot;
2798
+ }
2799
+ return out;
2800
+ }
2801
+ var DAEMON_ID_PREFIXES, MAGI_RAW_ANSWER_CAP, MESH_TASK_DIFFICULTIES, DEFAULT_DIFFICULTY_BRAINS, CANONICAL_MESH_TOOL_NAMES, CANONICAL_MESH_TOOL_COUNT;
2775
2802
  var init_dist = __esm({
2776
2803
  "../mesh-shared/dist/index.mjs"() {
2777
2804
  "use strict";
2778
2805
  DAEMON_ID_PREFIXES = ["daemon_", "standalone_"];
2779
2806
  MAGI_RAW_ANSWER_CAP = 4e3;
2807
+ MESH_TASK_DIFFICULTIES = ["easy", "medium", "difficult", "freeform"];
2808
+ DEFAULT_DIFFICULTY_BRAINS = {
2809
+ easy: { model: "haiku", thinkingLevel: "low" },
2810
+ medium: { model: "sonnet", thinkingLevel: "medium" },
2811
+ difficult: { model: "opus", thinkingLevel: "high" }
2812
+ };
2780
2813
  CANONICAL_MESH_TOOL_NAMES = [
2781
2814
  "mesh_status",
2782
2815
  "mesh_list_nodes",
@@ -2917,6 +2950,7 @@ __export(mesh_config_exports, {
2917
2950
  createMesh: () => createMesh,
2918
2951
  createMeshHostPairingToken: () => createMeshHostPairingToken,
2919
2952
  deleteMesh: () => deleteMesh,
2953
+ getDifficultyBrains: () => getDifficultyBrains,
2920
2954
  getMagiKindPanel: () => getMagiKindPanel,
2921
2955
  getMesh: () => getMesh,
2922
2956
  getMeshByRepo: () => getMeshByRepo,
@@ -2927,6 +2961,7 @@ __export(mesh_config_exports, {
2927
2961
  normalizeRepoIdentity: () => normalizeRepoIdentity,
2928
2962
  removeMagiKindPanel: () => removeMagiKindPanel,
2929
2963
  removeNode: () => removeNode,
2964
+ setDifficultyBrains: () => setDifficultyBrains,
2930
2965
  setMagiKindPanel: () => setMagiKindPanel,
2931
2966
  tokenIdForManualPairing: () => tokenIdForManualPairing,
2932
2967
  updateMesh: () => updateMesh,
@@ -3402,6 +3437,19 @@ function removeMagiKindPanel(kind) {
3402
3437
  saveMeshConfig(stored);
3403
3438
  return true;
3404
3439
  }
3440
+ function getDifficultyBrains() {
3441
+ const stored = loadMeshConfig().difficultyBrains;
3442
+ const normalized = normalizeDifficultyBrainMap(stored);
3443
+ return Object.keys(normalized).length > 0 ? normalized : { ...DEFAULT_DIFFICULTY_BRAINS };
3444
+ }
3445
+ function setDifficultyBrains(map) {
3446
+ const normalized = normalizeDifficultyBrainMap(map);
3447
+ const stored = loadMeshConfig();
3448
+ if (Object.keys(normalized).length > 0) stored.difficultyBrains = normalized;
3449
+ else delete stored.difficultyBrains;
3450
+ saveMeshConfig(stored);
3451
+ return normalized;
3452
+ }
3405
3453
  var import_fs3, import_path3, import_crypto3, mergeMeshPolicy, MAGI_KIND_PANEL_KINDS, MAX_MAGI_KIND_SLOTS;
3406
3454
  var init_mesh_config = __esm({
3407
3455
  "src/config/mesh-config.ts"() {
@@ -3411,6 +3459,7 @@ var init_mesh_config = __esm({
3411
3459
  import_crypto3 = require("crypto");
3412
3460
  init_hash();
3413
3461
  init_config();
3462
+ init_dist();
3414
3463
  init_repo_mesh_types();
3415
3464
  init_mesh_host_ownership();
3416
3465
  mergeMeshPolicy = mergeAndNormalizePolicy;
@@ -3507,6 +3556,7 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
3507
3556
  if (operatingNotes) sections.push(operatingNotes);
3508
3557
  }
3509
3558
  sections.push(buildPolicySection(mergeAndNormalizePolicy(void 0, mesh.policy)));
3559
+ sections.push(buildBrainPresetsSection());
3510
3560
  sections.push(TOOLS_SECTION);
3511
3561
  sections.push(TOOL_EXPOSURE_PREFLIGHT_SECTION);
3512
3562
  sections.push(WORKFLOW_SECTION);
@@ -3695,6 +3745,34 @@ function truncateNote(text) {
3695
3745
  if (text.length <= OPERATING_NOTE_MAX_CHARS) return text;
3696
3746
  return `${text.slice(0, OPERATING_NOTE_MAX_CHARS).trimEnd()}\u2026 [truncated]`;
3697
3747
  }
3748
+ function buildBrainPresetsSection() {
3749
+ let brains;
3750
+ try {
3751
+ brains = getDifficultyBrains();
3752
+ } catch {
3753
+ brains = {};
3754
+ }
3755
+ const lines = [
3756
+ "## Brain presets",
3757
+ "",
3758
+ "When you pass `difficulty` on `mesh_enqueue_task`, it resolves to this model / thinking level (an explicit model/thinkingLevel on the task overrides it). Pick easy for trivial work to save tokens, difficult for hard reasoning.",
3759
+ ""
3760
+ ];
3761
+ for (const key2 of MESH_TASK_DIFFICULTIES) {
3762
+ const slot = brains[key2];
3763
+ if (!slot || !slot.provider && !slot.model && !slot.thinkingLevel) {
3764
+ lines.push(`- **${key2}**: (no preset \u2014 ordinary routing)`);
3765
+ continue;
3766
+ }
3767
+ const parts = [
3768
+ slot.provider ? `provider: \`${slot.provider}\`` : "",
3769
+ slot.model ? `model: \`${slot.model}\`` : "",
3770
+ slot.thinkingLevel ? `thinking: \`${slot.thinkingLevel}\`` : ""
3771
+ ].filter(Boolean).join(" | ");
3772
+ lines.push(`- **${key2}**: ${parts}`);
3773
+ }
3774
+ return lines.join("\n");
3775
+ }
3698
3776
  function buildPolicySection(policy) {
3699
3777
  const rules = [];
3700
3778
  if (policy.requirePreTaskCheckpoint) rules.push("- Create a git checkpoint **before** starting each task");
@@ -3723,6 +3801,7 @@ function buildRulesSection(coordinatorCliType) {
3723
3801
  - **Front-load task messages.** Include everything the agent needs (files, problem, expected fix) in \`mesh_enqueue_task\` / \`mesh_send_task\`. Append a structured result request at the end: ask the worker to conclude with a JSON block containing \`status\`, \`changedFiles\`, \`gitStatus\`, \`validationResults\`, \`errors\`, \`nextAction\`. The daemon parses this automatically; you can read it from \`mesh_task_history\`.
3724
3802
  - **Reuse idle sessions.** For follow-up, retry, commit/push, or cleanup on the same issue, send only the delta to the existing idle session. Start fresh only for independent work, provider mismatch, transcript contamination, or required worktree isolation.
3725
3803
  - **Worktree affinity.** A worktree is a durable per-branch workspace; keep all of a branch's code_change/fix/review work on its worktree node by targeting \`required_tags: ["worktree=<branch>"]\` or \`target_node_id\`. Get the id/branch from the \`mesh_clone_node\` result or a live \`mesh_status\` \u2014 the Configured Nodes snapshot won't list a worktree cloned after launch. Untargeted same-branch follow-ups drift to the base node. Only \`convergence\` (merge/push) runs on the base, never pinned to the worktree.
3804
+ - **Classify task difficulty to save tokens.** For each task you enqueue, judge its execution difficulty and pass \`difficulty\`: \`easy\` (extraction, renames, doc tweaks, trivial fixes), \`medium\` (ordinary feature/bugfix work), \`difficult\` (architecture, tricky debugging, multi-file refactors, subtle reasoning), or \`freeform\`. The mesh's per-difficulty brain preset then runs easy tasks on a cheaper model at low reasoning effort and hard tasks on a stronger model at high effort \u2014 real token savings on simple work. The current presets are shown in the "Brain presets" section below. You may still pass an explicit \`model\`/\`thinkingLevel\` to override the preset for one task.
3726
3805
  - **Respect explicit provider requests.** Map: Hermes \u2192 \`hermes-cli\`, Claude/Claude Code \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`, Antigravity \u2192 \`antigravity-cli\`. Never substitute the coordinator's own runtime.
3727
3806
  - **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
3728
3807
  - **Limit parallelism.** Start with 1\u20132 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing. This caps *concurrent* load \u2014 it does not mean serialize independent work: when a new, independent request arrives and there is headroom under \`maxParallelTasks\`, dispatch it right away rather than waiting for an in-flight task or a user nudge (read-only diagnosis especially, since it has no merge cost).
@@ -3752,6 +3831,8 @@ var init_coordinator_prompt = __esm({
3752
3831
  os2 = __toESM(require("os"));
3753
3832
  path8 = __toESM(require("path"));
3754
3833
  init_repo_mesh_types();
3834
+ init_mesh_config();
3835
+ init_dist();
3755
3836
  PROMPT_SOFT_CAP_BYTES = 60 * 1024;
3756
3837
  OPERATING_NOTES_PROMPT_CAP = 20;
3757
3838
  OPERATING_NOTE_MAX_CHARS = 300;
@@ -5747,6 +5828,18 @@ function enqueueTask(meshId, message, opts) {
5747
5828
  const priority = normalizeMeshTaskPriority(opts?.priority);
5748
5829
  const notBefore = resolveNotBefore(opts?.notBefore);
5749
5830
  const maxRetries = typeof opts?.maxRetries === "number" && Number.isFinite(opts.maxRetries) && opts.maxRetries >= 0 ? Math.floor(opts.maxRetries) : void 0;
5831
+ let effectiveModel = typeof opts?.model === "string" && opts.model.trim() ? opts.model.trim() : void 0;
5832
+ let effectiveThinkingLevel = typeof opts?.thinkingLevel === "string" && opts.thinkingLevel.trim() ? opts.thinkingLevel.trim() : void 0;
5833
+ if (isMeshTaskDifficulty(opts?.difficulty)) {
5834
+ try {
5835
+ const preset = getDifficultyBrains()[opts.difficulty];
5836
+ if (preset) {
5837
+ if (!effectiveModel && preset.model) effectiveModel = preset.model;
5838
+ if (!effectiveThinkingLevel && preset.thinkingLevel) effectiveThinkingLevel = preset.thinkingLevel;
5839
+ }
5840
+ } catch {
5841
+ }
5842
+ }
5750
5843
  const result = withQueueLock(meshId, () => {
5751
5844
  if (MeshRuntimeStore.getInstance().findQueueEntryById(meshId, id)) {
5752
5845
  throw new Error(`duplicate_task_id: task '${id}' already exists in mesh '${meshId}'`);
@@ -5778,7 +5871,8 @@ function enqueueTask(meshId, message, opts) {
5778
5871
  ...maxRetries !== void 0 ? { maxRetries } : {},
5779
5872
  ...typeof opts?.missionId === "string" && opts.missionId.trim() ? { missionId: opts.missionId.trim() } : {},
5780
5873
  ...typeof opts?.consensusGroupId === "string" && opts.consensusGroupId.trim() ? { consensusGroupId: opts.consensusGroupId.trim() } : {},
5781
- ...typeof opts?.model === "string" && opts.model.trim() ? { model: opts.model.trim() } : {},
5874
+ ...effectiveModel ? { model: effectiveModel } : {},
5875
+ ...effectiveThinkingLevel ? { thinkingLevel: effectiveThinkingLevel } : {},
5782
5876
  ...typeof opts?.sourceCoordinatorSessionId === "string" && opts.sourceCoordinatorSessionId.trim() ? { sourceCoordinatorSessionId: opts.sourceCoordinatorSessionId.trim() } : {},
5783
5877
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
5784
5878
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -7353,6 +7447,27 @@ var init_mesh_runtime_store = __esm({
7353
7447
  `).get(meshId, taskId);
7354
7448
  return !!row;
7355
7449
  }
7450
+ /**
7451
+ * DELIVERED-NOT-CONSUMED re-drive support: true when at least one delivery record for
7452
+ * the task has reached a CONSUMED status ('acked' / 'completed'). Distinct from
7453
+ * {@link taskHasConfirmedDelivery} ('delivered' | 'acked' | 'completed'): a delivery is
7454
+ * flipped to 'delivered' the instant the transport hands the dispatch off, but only
7455
+ * flipped to 'acked' when the worker's agent:generating_started event arrives (see the
7456
+ * generating_started handler in mesh-event-forwarding) — i.e. when the session has
7457
+ * actually begun the turn. That distinction is the cross-daemon consumption signal the
7458
+ * short-grace re-drive uses: a row whose delivery is 'delivered' but never 'acked' was
7459
+ * handed to a REMOTE worker that never started generating — the remote autoLaunch
7460
+ * delivered≠consumed gap — even when the session's busy verdict is UNKNOWN (not locally
7461
+ * observable). Indexed by (mesh_id, task_id).
7462
+ */
7463
+ taskDeliveryConsumed(meshId, taskId) {
7464
+ const row = this.db.prepare(`
7465
+ SELECT 1 FROM mesh_session_delivery
7466
+ WHERE mesh_id = ? AND task_id = ? AND status IN ('acked','completed')
7467
+ LIMIT 1
7468
+ `).get(meshId, taskId);
7469
+ return !!row;
7470
+ }
7356
7471
  expireStaleSessionDeliveries(meshId) {
7357
7472
  const now = (/* @__PURE__ */ new Date()).toISOString();
7358
7473
  this.db.prepare(`
@@ -8442,7 +8557,8 @@ function routeV2EventsForDrainer(events, drainer, ctx) {
8442
8557
  }
8443
8558
  if (validated.scope !== "unicast") {
8444
8559
  if (validated.scope === "broadcast" && isTerminalTaskEvent(validated.event)) {
8445
- if (identityDeliversTo(validated.dispatchedBy, drainer)) {
8560
+ const deliverSelfFallback = event.dispatchedBySelfFallback && daemonIdsEquivalent(validated.dispatchedBy.daemonId, drainer.daemonId);
8561
+ if (deliverSelfFallback || identityDeliversTo(validated.dispatchedBy, drainer)) {
8446
8562
  ctx.batchSeen.add(eventId);
8447
8563
  bump("v2Delivered");
8448
8564
  kept.push(event);
@@ -8714,13 +8830,15 @@ function stampPendingEventV2(event, hint) {
8714
8830
  scope: hint?.scope ?? (selfFallback ? "broadcast" : void 0)
8715
8831
  });
8716
8832
  if (!stamp) return event;
8833
+ const dispatchedBySelfFallback = selfFallback && stamp.scope === "broadcast";
8717
8834
  return {
8718
8835
  ...event,
8719
8836
  protocolVersion: stamp.protocolVersion,
8720
8837
  eventId: stamp.eventId,
8721
8838
  scope: stamp.scope,
8722
8839
  dispatchedBy: stamp.dispatchedBy,
8723
- ...stamp.intendedFor ? { intendedFor: stamp.intendedFor } : {}
8840
+ ...stamp.intendedFor ? { intendedFor: stamp.intendedFor } : {},
8841
+ ...dispatchedBySelfFallback ? { dispatchedBySelfFallback: true } : {}
8724
8842
  };
8725
8843
  }
8726
8844
  function readCoordinatorIdentityFromWire(raw) {
@@ -15237,6 +15355,24 @@ function getMeshWithCache(components, meshId) {
15237
15355
  if (!cachedMesh) return localMesh;
15238
15356
  return mergeInlineCacheOnlyNodes(localMesh, cachedMesh);
15239
15357
  }
15358
+ function bootstrapEpochMs(bootstrap) {
15359
+ const raw = readNonEmptyString2(bootstrap?.startedAt) || readNonEmptyString2(bootstrap?.completedAt);
15360
+ if (!raw) return 0;
15361
+ const parsed = Date.parse(raw);
15362
+ return Number.isFinite(parsed) ? parsed : 0;
15363
+ }
15364
+ function inlineBootstrapIsFresher(inlineBootstrap, configBootstrap) {
15365
+ const inlineStatus = readNonEmptyString2(inlineBootstrap?.status);
15366
+ if (!inlineStatus) return false;
15367
+ const configStatus = readNonEmptyString2(configBootstrap?.status);
15368
+ const inlineTerminal = BOOTSTRAP_TERMINAL_STATUSES.has(inlineStatus);
15369
+ const configTerminal = !!configStatus && BOOTSTRAP_TERMINAL_STATUSES.has(configStatus);
15370
+ if (configTerminal) {
15371
+ return inlineTerminal && inlineStatus !== configStatus && bootstrapEpochMs(inlineBootstrap) > bootstrapEpochMs(configBootstrap);
15372
+ }
15373
+ if (inlineTerminal) return true;
15374
+ return bootstrapEpochMs(inlineBootstrap) > bootstrapEpochMs(configBootstrap);
15375
+ }
15240
15376
  function mergeInlineCacheOnlyNodes(localMesh, cachedMesh) {
15241
15377
  const localNodes = Array.isArray(localMesh?.nodes) ? localMesh.nodes : [];
15242
15378
  const cachedNodes = Array.isArray(cachedMesh?.nodes) ? cachedMesh.nodes : [];
@@ -15246,8 +15382,23 @@ function mergeInlineCacheOnlyNodes(localMesh, cachedMesh) {
15246
15382
  if (!cachedId) return false;
15247
15383
  return !localNodes.some((localNode) => meshNodeIdMatches(localNode, cachedId));
15248
15384
  });
15249
- if (!cacheOnly.length) return localMesh;
15250
- return { ...localMesh, nodes: [...localNodes, ...cacheOnly] };
15385
+ let overlaidLocalNodes = localNodes;
15386
+ let overlaid = false;
15387
+ for (let i = 0; i < localNodes.length; i++) {
15388
+ const localNode = localNodes[i];
15389
+ const localId = readMeshNodeId(localNode);
15390
+ if (!localId) continue;
15391
+ const inlineMatch = cachedNodes.find((cachedNode) => meshNodeIdMatches(cachedNode, localId));
15392
+ if (!inlineMatch) continue;
15393
+ if (!inlineBootstrapIsFresher(inlineMatch.worktreeBootstrap, localNode.worktreeBootstrap)) continue;
15394
+ if (!overlaid) {
15395
+ overlaidLocalNodes = [...localNodes];
15396
+ overlaid = true;
15397
+ }
15398
+ overlaidLocalNodes[i] = { ...localNode, worktreeBootstrap: inlineMatch.worktreeBootstrap };
15399
+ }
15400
+ if (!cacheOnly.length && !overlaid) return localMesh;
15401
+ return { ...localMesh, nodes: [...overlaidLocalNodes, ...cacheOnly] };
15251
15402
  }
15252
15403
  function warnDispatchWarmupGetterMissingOnce(daemonId) {
15253
15404
  if (dispatchWarmupGetterMissingWarned.has(daemonId)) return;
@@ -16117,7 +16268,9 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
16117
16268
  settings: remoteSettings,
16118
16269
  // MAGI-KIND-PANEL model axis: forward the task's model override so the
16119
16270
  // remote worker session launches with it (initialModel). Best-effort.
16120
- ...typeof task.model === "string" && task.model.trim() ? { initialModel: task.model.trim() } : {}
16271
+ ...typeof task.model === "string" && task.model.trim() ? { initialModel: task.model.trim() } : {},
16272
+ // BRAIN-ROUTING thinking axis: forward the task's thinking level (initialThinkingLevel).
16273
+ ...typeof task.thinkingLevel === "string" && task.thinkingLevel.trim() ? { initialThinkingLevel: task.thinkingLevel.trim() } : {}
16121
16274
  });
16122
16275
  } catch (e) {
16123
16276
  markAutoLaunch(meshId, task.id, { status: "failed", reason: `remote_launch_dispatch_failed: ${e?.message || String(e)}`, nodeId, providerType: resolved.providerType });
@@ -16146,7 +16299,9 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
16146
16299
  settings: launchSettings,
16147
16300
  // MAGI-KIND-PANEL model axis: local launch forwards the task's model
16148
16301
  // override as initialModel (CLI → modelLaunchArgs; ACP → setConfigOption).
16149
- ...typeof task.model === "string" && task.model.trim() ? { initialModel: task.model.trim() } : {}
16302
+ ...typeof task.model === "string" && task.model.trim() ? { initialModel: task.model.trim() } : {},
16303
+ // BRAIN-ROUTING thinking axis: forward the task's thinking level (initialThinkingLevel).
16304
+ ...typeof task.thinkingLevel === "string" && task.thinkingLevel.trim() ? { initialThinkingLevel: task.thinkingLevel.trim() } : {}
16150
16305
  });
16151
16306
  if (!launchResult?.success) {
16152
16307
  const reason = launchResult?.error || "launch_cli_failed";
@@ -16384,7 +16539,7 @@ function runIdleMaintenanceThenAssignQueue(components, args) {
16384
16539
  });
16385
16540
  });
16386
16541
  }
16387
- var import_fs13, IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, LOCAL_LAUNCH_READY_TIMEOUT_MS, LOCAL_LAUNCH_READY_POLL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES, AUTO_LAUNCH_REMOTE_IDLE_TTL_MS, autoLaunchAwaitClaimBackoff, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, ACTIONABLE_SKIP_REASON_PREFIXES, TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON, lastActionableSkipNotified;
16542
+ var import_fs13, IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, BOOTSTRAP_TERMINAL_STATUSES, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, LOCAL_LAUNCH_READY_TIMEOUT_MS, LOCAL_LAUNCH_READY_POLL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES, AUTO_LAUNCH_REMOTE_IDLE_TTL_MS, autoLaunchAwaitClaimBackoff, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, ACTIONABLE_SKIP_REASON_PREFIXES, TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON, lastActionableSkipNotified;
16388
16543
  var init_mesh_queue_assignment = __esm({
16389
16544
  "src/mesh/mesh-queue-assignment.ts"() {
16390
16545
  "use strict";
@@ -16412,6 +16567,7 @@ var init_mesh_queue_assignment = __esm({
16412
16567
  init_mesh_task_inflight();
16413
16568
  IDLE_AUTO_FAST_FORWARD_THROTTLE_MS = 30 * 60 * 1e3;
16414
16569
  idleAutoFastForwardLastAttempt = /* @__PURE__ */ new Map();
16570
+ BOOTSTRAP_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["complete", "failed"]);
16415
16571
  DISPATCH_CONFIRM_TIMEOUT_MS = 12e4;
16416
16572
  DISPATCH_CONNECT_TIMEOUT_MS = MESH_CONNECT_TIMEOUT_MS;
16417
16573
  dispatchWarmupGetterMissingWarned = /* @__PURE__ */ new Set();
@@ -18706,6 +18862,8 @@ function buildAvailableProviders(providerLoader) {
18706
18862
  ...sourceLayer ? { sourceLayer } : {},
18707
18863
  ...sourceName ? { sourceName } : {},
18708
18864
  ...provider.providerVersion ? { providerVersion: provider.providerVersion } : {},
18865
+ ...Array.isArray(provider.modelOptions) && provider.modelOptions.length ? { modelOptions: provider.modelOptions } : {},
18866
+ ...Array.isArray(provider.thinkingLevelOptions) && provider.thinkingLevelOptions.length ? { thinkingLevelOptions: provider.thinkingLevelOptions } : {},
18709
18867
  ...provider.binary ? { binary: provider.binary } : {},
18710
18868
  ...provider.status ? { status: provider.status } : {},
18711
18869
  ...provider.details ? { details: provider.details } : {},
@@ -21043,7 +21201,34 @@ function recoverStrandedAssignedDispatches(components, meshId, store) {
21043
21201
  for (const row of assigned) {
21044
21202
  const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? "");
21045
21203
  if (!Number.isFinite(dispatchedAtMs)) continue;
21046
- if (nowMs - dispatchedAtMs < ASSIGNED_STRANDED_DEADLINE_MS) continue;
21204
+ const ageMs = nowMs - dispatchedAtMs;
21205
+ if (ageMs >= ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS && ageMs < ASSIGNED_STRANDED_DEADLINE_MS && store.taskHasConfirmedDelivery(meshId, row.id) && !store.taskDeliveryConsumed(meshId, row.id)) {
21206
+ const terminal2 = findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id });
21207
+ if (terminal2) {
21208
+ const status = terminal2.kind === "task_completed" ? "completed" : "failed";
21209
+ updateTaskStatus(meshId, row.id, status);
21210
+ continue;
21211
+ }
21212
+ const verdict = row.assignedSessionId ? resolveSessionBusyVerdict(components, row.assignedSessionId) : "IDLE_CONFIRMED";
21213
+ if (verdict !== "GENERATING") {
21214
+ const redriven = reclaimStrandedAssignedTask(meshId, row.id, {
21215
+ reason: "delivered_not_consumed_redrive",
21216
+ ageMs
21217
+ });
21218
+ if (redriven) {
21219
+ LOG.warn("MeshReconcile", `Re-drove delivered-but-unconsumed task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}, delivered but no generating_started in ${Math.round(ageMs / 1e3)}s, verdict ${verdict} \u2192 ${redriven.status})`);
21220
+ traceMeshEventDrop("assigned_delivered_not_consumed_redrive", {
21221
+ taskId: row.id,
21222
+ sessionId: row.assignedSessionId,
21223
+ nodeId: row.assignedNodeId,
21224
+ meshId,
21225
+ event: "agent:generating_started"
21226
+ }, `delivered_not_consumed ${Math.round(ageMs / 1e3)}s \u2192 ${redriven.status}`);
21227
+ continue;
21228
+ }
21229
+ }
21230
+ }
21231
+ if (ageMs < ASSIGNED_STRANDED_DEADLINE_MS) continue;
21047
21232
  const terminal = findTerminalLedgerEvidenceForTask({
21048
21233
  meshId,
21049
21234
  taskId: row.id
@@ -21558,7 +21743,7 @@ function setupMeshReconcileLoop(components) {
21558
21743
  }
21559
21744
  };
21560
21745
  }
21561
- var coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, ZOMBIE_ASSIGNED_MIN_AGE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS, UNRESOLVED_FORWARD_NUDGE_DELAY_MS, unresolvedForwardNudgeTimer, unresolvedForwardNudgeRunning;
21746
+ var coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, ZOMBIE_ASSIGNED_MIN_AGE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS, UNRESOLVED_FORWARD_NUDGE_DELAY_MS, unresolvedForwardNudgeTimer, unresolvedForwardNudgeRunning;
21562
21747
  var init_mesh_reconcile_loop = __esm({
21563
21748
  "src/mesh/mesh-reconcile-loop.ts"() {
21564
21749
  "use strict";
@@ -21588,6 +21773,7 @@ var init_mesh_reconcile_loop = __esm({
21588
21773
  heldEventLedgerRecorded = /* @__PURE__ */ new Set();
21589
21774
  ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
21590
21775
  DELIVERED_NO_TURN_DEADLINE_MS = 15 * 6e4;
21776
+ ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS = 25e3;
21591
21777
  RECLAIM_UNKNOWN_GRACE_TICKS = 3;
21592
21778
  deliveredNoTurnUnknownStreak = /* @__PURE__ */ new Map();
21593
21779
  ZOMBIE_ASSIGNED_MIN_AGE_MS = 30 * 60 * 1e3;
@@ -21863,6 +22049,35 @@ var init_provider_schema = __esm({
21863
22049
  items: { type: "string" },
21864
22050
  description: "Template for expanding an initialModel selection into launch args. '{{model}}' is substituted with the model string (e.g. ['--model', '{{model}}'] \u2192 --model opus). Applied at launch when a model is requested for this CLI provider (MAGI kind-panel model axis). Absent \u2192 no launch-time model selection."
21865
22051
  },
22052
+ modelOptions: {
22053
+ type: "array",
22054
+ items: { type: "string" },
22055
+ description: "Suggested model values shown as dropdown options in the new-session dialog (brain-routing model axis), e.g. ['opus','sonnet','haiku']. Advisory \u2014 the UI still accepts free text, so a stale list never blocks an accepted model."
22056
+ },
22057
+ thinkingLaunchArgs: {
22058
+ type: "array",
22059
+ items: { type: "string" },
22060
+ description: "Template for expanding an initialThinkingLevel selection into launch args (brain-routing thinking axis, parallel to modelLaunchArgs). '{{level}}' is substituted with the provider-mapped reasoning-effort value (e.g. ['--effort', '{{level}}'] \u2192 --effort high; ['-c', 'model_reasoning_effort={{level}}']). Applied at launch when a thinking level is requested. Absent \u2192 no launch-time thinking selection."
22061
+ },
22062
+ thinkingLevelMap: {
22063
+ type: "object",
22064
+ properties: {
22065
+ low: { type: "string" },
22066
+ medium: { type: "string" },
22067
+ high: { type: "string" }
22068
+ },
22069
+ additionalProperties: false,
22070
+ description: "Optional map from the standard thinking levels (low/medium/high) to this provider's own reasoning-effort vocabulary, used to fill {{level}} in thinkingLaunchArgs. A level absent from the map passes through unchanged."
22071
+ },
22072
+ thinkingLevelOptions: {
22073
+ type: "array",
22074
+ items: { type: "string" },
22075
+ description: "Reasoning-effort values this provider accepts, shown as the thinking-level dropdown in the new-session dialog (e.g. ['low','medium','high','max']). Absent \u2192 the UI falls back to standard low/medium/high. Provider's own vocabulary, passed through verbatim."
22076
+ },
22077
+ thinkingControlId: {
22078
+ type: "string",
22079
+ description: "For a provider with no thinkingLaunchArgs but a runtime reasoning-effort control (e.g. hermes 'reasoning'), the controls[].id to drive at launch for the thinking level. The control's setScript is invoked with { value: <mapped level> }."
22080
+ },
21866
22081
  scriptCallBudgetMs: {
21867
22082
  type: "integer",
21868
22083
  minimum: 1,
@@ -25299,6 +25514,13 @@ var init_provider_cli_adapter = __esm({
25299
25514
  lastScreenSnapshot = "";
25300
25515
  lastScreenText = "";
25301
25516
  lastScreenSnapshotReadAt = Number.NEGATIVE_INFINITY;
25517
+ // (FALSEIDLE Path-C) Count of CONSECUTIVE getStatus polls that observed a
25518
+ // gate-eligible static-idle screen (detect=idle, no modal, quiet, empty
25519
+ // partial buffer). For a mesh/autonomous worker we require several such
25520
+ // polls in a row before confirming static-idle (see getStatus), so a
25521
+ // single momentarily-silent point-sample of a still-live turn cannot flip
25522
+ // it. Reset to 0 the instant any poll is ineligible.
25523
+ staticIdlePollStreak = 0;
25302
25524
  // Server log forwarding
25303
25525
  serverConn = null;
25304
25526
  logBuffer = [];
@@ -25364,6 +25586,13 @@ var init_provider_cli_adapter = __esm({
25364
25586
  static MAX_ACCUMULATED_BUFFER = 262144;
25365
25587
  parsedStatusCache = null;
25366
25588
  static SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
25589
+ // (FALSEIDLE Path-C) Consecutive gate-eligible getStatus polls a mesh/autonomous
25590
+ // session must show before the poll-static-idle confirm fires. 2 = one extra
25591
+ // status tick of hysteresis: enough to reject a single momentary-silence
25592
+ // point-sample of a still-live turn, cheap enough not to materially delay a
25593
+ // genuine boot-wedge release (the wedge screen is stably static, so it clears
25594
+ // every consecutive poll and confirms on the 2nd).
25595
+ static STATIC_IDLE_POLL_CONFIRM_COUNT = 2;
25367
25596
  providerResolutionMeta;
25368
25597
  getBufferState() {
25369
25598
  const build = (droppedChars, maxChars) => droppedChars > 0 ? { truncated: true, droppedChars, maxChars } : void 0;
@@ -25435,6 +25664,18 @@ ${lastSnapshot}`;
25435
25664
  getStatusActivityHoldMs() {
25436
25665
  return this.timeouts.statusActivityHold;
25437
25666
  }
25667
+ // (FALSEIDLE Path-C) Whether this session is a mesh worker or coordinator's
25668
+ // own autonomous session. Mirrors CliProviderInstance.isAutonomousMeshSession
25669
+ // over the runtimeSettings the instance mirrors down via updateRuntimeSettings
25670
+ // (meshNodeFor / meshActiveTaskId / meshNodeId / launchedByCoordinator =
25671
+ // isMeshWorkerSession, plus meshCoordinatorFor for the coordinator's own turn).
25672
+ // Such a session has no human at the keyboard to correct a premature idle, so
25673
+ // the poll-static-idle confirm is debounced for it (multiple consecutive idle
25674
+ // polls) rather than fired on a single point-sample.
25675
+ isAutonomousMeshSession() {
25676
+ const s2 = this.runtimeSettings;
25677
+ return !!(s2?.meshNodeFor || s2?.meshActiveTaskId || s2?.meshNodeId || s2?.launchedByCoordinator || s2?.meshCoordinatorFor);
25678
+ }
25438
25679
  // Resolved timeouts
25439
25680
  timeouts;
25440
25681
  // Provider approval key mapping
@@ -25822,14 +26063,27 @@ ${lastSnapshot}`;
25822
26063
  if (allowParse && this.engine.currentStatus === "generating" && !this.engine.currentTurnScope && !this.engine.activeModal) {
25823
26064
  const now = Date.now();
25824
26065
  const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
26066
+ let eligible = false;
25825
26067
  if (quietForMs >= this.getStatusActivityHoldMs()) {
25826
26068
  const screenText = this.terminalScreen.getText();
25827
26069
  const pollDetect = this.runDetectStatus(screenText || this.recentOutputBuffer);
25828
26070
  const pollModal = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
25829
- if (pollDetect === "idle" && !pollModal) {
26071
+ const partial = this.getPartialResponse();
26072
+ const partialPending = typeof partial === "string" && partial.trim().length > 0;
26073
+ eligible = pollDetect === "idle" && !pollModal && !partialPending;
26074
+ }
26075
+ if (eligible) {
26076
+ const requiredStreak = this.isAutonomousMeshSession() ? _ProviderCliAdapter.STATIC_IDLE_POLL_CONFIRM_COUNT : 1;
26077
+ this.staticIdlePollStreak += 1;
26078
+ if (this.staticIdlePollStreak >= requiredStreak) {
25830
26079
  this.engine.confirmPollStaticIdle("poll_static_idle");
26080
+ this.staticIdlePollStreak = 0;
25831
26081
  }
26082
+ } else {
26083
+ this.staticIdlePollStreak = 0;
25832
26084
  }
26085
+ } else {
26086
+ this.staticIdlePollStreak = 0;
25833
26087
  }
25834
26088
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
25835
26089
  let effectiveModal = startupModal || this.engine.activeModal;
@@ -44967,6 +45221,7 @@ var CliProviderInstance = class _CliProviderInstance {
44967
45221
  this.presentationMode = "chat";
44968
45222
  this.providerSessionId = options?.providerSessionId;
44969
45223
  this.launchMode = options?.launchMode || "new";
45224
+ this.initialThinkingLevel = options?.initialThinkingLevel;
44970
45225
  this.onProviderSessionResolved = options?.onProviderSessionResolved;
44971
45226
  this.adapter = createCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
44972
45227
  if (this.providerSessionId) {
@@ -45188,6 +45443,7 @@ var CliProviderInstance = class _CliProviderInstance {
45188
45443
  presentationMode;
45189
45444
  providerSessionId;
45190
45445
  launchMode;
45446
+ initialThinkingLevel;
45191
45447
  startedAt = Date.now();
45192
45448
  onProviderSessionResolved;
45193
45449
  refreshProviderDefinition(provider) {
@@ -45216,6 +45472,7 @@ var CliProviderInstance = class _CliProviderInstance {
45216
45472
  });
45217
45473
  await this.adapter.spawn();
45218
45474
  await this.enforceFreshSessionLaunchIfNeeded();
45475
+ await this.applyInitialThinkingLevelViaControl();
45219
45476
  this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
45220
45477
  if (this.providerSessionId && this.shouldHydrateExistingProviderHistory()) {
45221
45478
  this.restorePersistedHistoryFromCurrentSession();
@@ -45833,6 +46090,43 @@ var CliProviderInstance = class _CliProviderInstance {
45833
46090
  }
45834
46091
  this.applyProviderResponse(parsed.payload, { phase: "immediate" });
45835
46092
  }
46093
+ /**
46094
+ * BRAIN-ROUTING (runtime-control thinking axis): for a provider that selects
46095
+ * reasoning effort via a runtime control instead of a launch arg (e.g. hermes
46096
+ * `reasoning`), apply the requested initialThinkingLevel after spawn by invoking
46097
+ * that control's setScript. The provider names the control via thinkingControlId.
46098
+ * The standard level is mapped through thinkingLevelMap first (same as the
46099
+ * launch-arg path). Best-effort: any failure logs and never blocks launch.
46100
+ */
46101
+ async applyInitialThinkingLevelViaControl() {
46102
+ const level = typeof this.initialThinkingLevel === "string" ? this.initialThinkingLevel.trim() : "";
46103
+ if (!level) return;
46104
+ const controlId = this.provider.thinkingControlId;
46105
+ if (!controlId) return;
46106
+ const controls = Array.isArray(this.provider.controls) ? this.provider.controls : [];
46107
+ const control = controls.find((c) => c && c.id === controlId);
46108
+ if (!control || !control.setScript) return;
46109
+ const map = this.provider.thinkingLevelMap;
46110
+ const mapped = map && typeof map[level] === "string" && map[level].trim() ? map[level].trim() : level;
46111
+ try {
46112
+ await waitForCliAdapterReady(this.adapter);
46113
+ const raw = await this.adapter.invokeScript(control.setScript, { value: mapped });
46114
+ const parsed = parseCliScriptResult(raw);
46115
+ if (!parsed.success) {
46116
+ LOG.warn("CLI", `[${this.type}] thinking control '${controlId}' set to '${mapped}' failed: ${parsed.payload?.error || "unknown"}`);
46117
+ return;
46118
+ }
46119
+ const cliCommand = getCliScriptCommand(parsed.payload);
46120
+ if (cliCommand?.type === "send_message" && cliCommand.text) {
46121
+ await this.adapter.sendMessage(cliCommand.text);
46122
+ } else if (cliCommand?.type === "pty_write" && cliCommand.text) {
46123
+ await this.adapter.writeRaw(cliCommand.text + "\r");
46124
+ }
46125
+ LOG.info("CLI", `[${this.type}] applied thinking level '${mapped}' via control '${controlId}'`);
46126
+ } catch (e) {
46127
+ LOG.warn("CLI", `[${this.type}] thinking control apply threw: ${e?.message || e}`);
46128
+ }
46129
+ }
45836
46130
  completionHasFinalAssistantMessage(messages, turnStartedAt) {
45837
46131
  const visibleMessages = (Array.isArray(messages) ? messages : []).filter((message) => isUserFacingChatMessage(message));
45838
46132
  const lastVisible = visibleMessages[visibleMessages.length - 1];
@@ -48939,7 +49233,13 @@ function expandResumeArgs(template, sessionId) {
48939
49233
  function expandModelLaunchArgs(template, model) {
48940
49234
  const m = typeof model === "string" ? model.trim() : "";
48941
49235
  if (!m || !Array.isArray(template) || template.length === 0) return void 0;
48942
- return template.map((part) => part === "{{model}}" ? m : part);
49236
+ return template.map((part) => part.includes("{{model}}") ? part.split("{{model}}").join(m) : part);
49237
+ }
49238
+ function expandThinkingLaunchArgs(template, level, levelMap) {
49239
+ const raw = typeof level === "string" ? level.trim() : "";
49240
+ if (!raw || !Array.isArray(template) || template.length === 0) return void 0;
49241
+ const mapped = levelMap && typeof levelMap[raw] === "string" && levelMap[raw].trim() ? levelMap[raw].trim() : raw;
49242
+ return template.map((part) => part.includes("{{level}}") ? part.replace("{{level}}", mapped) : part);
48943
49243
  }
48944
49244
  function readSubcommandSessionId(args, subcommands) {
48945
49245
  const resumeIndex = args.findIndex((arg) => subcommands.includes(arg));
@@ -49323,6 +49623,15 @@ ${installInfo}`
49323
49623
  LOG.warn("CLI", `[ACP] Initial model set failed: ${e?.message}`);
49324
49624
  }
49325
49625
  }
49626
+ if (options?.initialThinkingLevel) {
49627
+ const lvl = options.initialThinkingLevel;
49628
+ try {
49629
+ await acpInstance.setConfigOption("thought_level", lvl);
49630
+ console.log(colorize("green", ` \u{1F9E0} Initial thinking level set: ${lvl}`));
49631
+ } catch (e) {
49632
+ LOG.warn("CLI", `[ACP] Initial thinking level set failed (provider may not support thought_level): ${e?.message}`);
49633
+ }
49634
+ }
49326
49635
  this.persistRecentActivity({
49327
49636
  kind: "acp",
49328
49637
  providerType: normalizedType,
@@ -49358,7 +49667,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
49358
49667
  if (initialModel && !modelLaunchArgs) {
49359
49668
  LOG.warn("CLI", `[${normalizedType}] initialModel='${initialModel}' requested but provider declares no modelLaunchArgs template \u2014 launching without model selection.`);
49360
49669
  }
49361
- const sessionBinding = resolveCliSessionBinding(provider, normalizedType, cliArgsWithModel, options?.resumeSessionId);
49670
+ const initialThinkingLevel = options?.initialThinkingLevel;
49671
+ const thinkingLaunchArgs = expandThinkingLaunchArgs(provider?.thinkingLaunchArgs, initialThinkingLevel, provider?.thinkingLevelMap);
49672
+ const cliArgsWithBrain = thinkingLaunchArgs ? [...thinkingLaunchArgs, ...cliArgsWithModel || []] : cliArgsWithModel;
49673
+ if (initialThinkingLevel && !thinkingLaunchArgs) {
49674
+ LOG.warn("CLI", `[${normalizedType}] initialThinkingLevel='${initialThinkingLevel}' requested but provider declares no thinkingLaunchArgs template \u2014 launching without thinking-level selection.`);
49675
+ }
49676
+ const sessionBinding = resolveCliSessionBinding(provider, normalizedType, cliArgsWithBrain, options?.resumeSessionId);
49362
49677
  const resolvedCliArgs = sessionBinding.cliArgs;
49363
49678
  const instanceManager = this.deps.getInstanceManager();
49364
49679
  if (provider && instanceManager) {
@@ -49376,6 +49691,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
49376
49691
  providerSessionId: sessionBinding.providerSessionId,
49377
49692
  launchMode: sessionBinding.launchMode,
49378
49693
  extraEnv: options?.extraEnv,
49694
+ // BRAIN-ROUTING: for a provider with no thinkingLaunchArgs but a
49695
+ // runtime reasoning control (hermes), apply the level post-launch.
49696
+ // The launch-arg providers (claude/codex) already consumed it at spawn.
49697
+ ...options?.initialThinkingLevel && !provider?.thinkingLaunchArgs ? { initialThinkingLevel: options.initialThinkingLevel } : {},
49379
49698
  onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
49380
49699
  this.persistRecentActivity({
49381
49700
  kind: "cli",
@@ -49723,7 +50042,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
49723
50042
  {
49724
50043
  resumeSessionId: args?.resumeSessionId,
49725
50044
  settingsOverride,
49726
- extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env
50045
+ extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env,
50046
+ ...typeof args?.initialThinkingLevel === "string" && args.initialThinkingLevel.trim() ? { initialThinkingLevel: args.initialThinkingLevel.trim() } : {}
49727
50047
  }
49728
50048
  );
49729
50049
  return {
@@ -50168,6 +50488,12 @@ var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
50168
50488
  "providerVersion",
50169
50489
  "status",
50170
50490
  "details",
50491
+ "modelLaunchArgs",
50492
+ "modelOptions",
50493
+ "thinkingLaunchArgs",
50494
+ "thinkingLevelMap",
50495
+ "thinkingLevelOptions",
50496
+ "thinkingControlId",
50171
50497
  "sendDelayMs",
50172
50498
  "sendKey",
50173
50499
  "submitStrategy",
@@ -54881,6 +55207,26 @@ var meshCrudHandlers = {
54881
55207
  return { success: false, error: e.message };
54882
55208
  }
54883
55209
  },
55210
+ // ─── Brain routing: per-difficulty brain presets (machine-local) ───
55211
+ // getDifficultyBrains returns the seeded defaults when nothing is configured,
55212
+ // so the editor always shows a usable mapping. set replaces the whole map.
55213
+ difficulty_brains_get: async (_ctx, _args) => {
55214
+ try {
55215
+ const { getDifficultyBrains: getDifficultyBrains2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
55216
+ return { success: true, difficultyBrains: getDifficultyBrains2() };
55217
+ } catch (e) {
55218
+ return { success: false, error: e.message };
55219
+ }
55220
+ },
55221
+ difficulty_brains_set: async (_ctx, args) => {
55222
+ try {
55223
+ const { setDifficultyBrains: setDifficultyBrains2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
55224
+ const difficultyBrains = setDifficultyBrains2(args?.difficultyBrains);
55225
+ return { success: true, difficultyBrains };
55226
+ } catch (e) {
55227
+ return { success: false, error: e.message };
55228
+ }
55229
+ },
54884
55230
  add_mesh_node: async (ctx, args) => {
54885
55231
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
54886
55232
  const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";