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

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.d.ts CHANGED
@@ -102,7 +102,7 @@ export { maybeRunDaemonUpgradeHelperFromEnv, spawnDetachedDaemonUpgradeHelper, r
102
102
  export type { DaemonUpgradeHelperPayload, CurrentGlobalInstallSurface, PinnedGlobalInstallCommand, NpmExecOptions, } from './commands/upgrade-helper.js';
103
103
  export { DaemonStatusReporter } from './status/reporter.js';
104
104
  export { buildSessionEntries, findCdpManager, hasCdpManager, isCdpConnected } from './status/builders.js';
105
- export { buildStatusSnapshot, buildMachineInfo, getLastDisplayMessage } from './status/snapshot.js';
105
+ export { buildStatusSnapshot, buildMachineInfo, buildAvailableProviders, getLastDisplayMessage } from './status/snapshot.js';
106
106
  export { getDaemonBuildInfo } from './build-info.js';
107
107
  export type { DaemonBuildInfo } from './build-info.js';
108
108
  export { normalizeManagedStatus, isManagedStatusWorking, isManagedStatusWaiting, normalizeActiveChatData } from './status/normalize.js';
package/dist/index.js CHANGED
@@ -145,7 +145,8 @@ var init_repo_mesh_types = __esm({
145
145
  "first_eligible",
146
146
  "least_loaded",
147
147
  "round_robin",
148
- "priority_only"
148
+ "priority_only",
149
+ "fitness"
149
150
  ];
150
151
  DEFAULT_MESH_SCHEDULING_STRATEGY = "first_eligible";
151
152
  MESH_CONVERGE_REFINE_TAG = "converge=refine";
@@ -157,7 +158,11 @@ var init_repo_mesh_types = __esm({
157
158
  allowAutoPublishSubmoduleMainCommits: false,
158
159
  requireApprovalForDestructiveGit: true,
159
160
  dirtyWorkspaceBehavior: "warn",
160
- maxParallelTasks: 2,
161
+ // Mesh-wide task cap is effectively unlimited by default: the real concurrency
162
+ // limits live per node / per capability slot (ORCHESTRATION_NODE_SLOTS.md), so a
163
+ // global ceiling is rarely meaningful. The UI hides this control; set it via the
164
+ // API only to impose a deliberate mesh-wide cap.
165
+ maxParallelTasks: 200,
161
166
  // Coordinator-spawned worker sessions default to hidden so the dashboard is not
162
167
  // flooded with mesh noise tabs/notifications. Users can still surface or unmute
163
168
  // any specific session manually; that override is preserved per-device.
@@ -409,10 +414,10 @@ function readInjected(value) {
409
414
  }
410
415
  function getDaemonBuildInfo() {
411
416
  if (cached) return cached;
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);
417
+ const commit = readInjected(true ? "cae0f42043ded25e4d3bed93d9f658035c09e007" : void 0) ?? "unknown";
418
+ const commitShort = readInjected(true ? "cae0f420" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
419
+ const version = readInjected(true ? "0.9.82-rc.486" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
420
+ const builtAt = readInjected(true ? "2026-07-09T23:19:53.642Z" : void 0);
416
421
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
417
422
  return cached;
418
423
  }
@@ -2798,6 +2803,74 @@ function normalizeDifficultyBrainMap(raw) {
2798
2803
  }
2799
2804
  return out;
2800
2805
  }
2806
+ function normalizeNodeCapabilitySlot(raw) {
2807
+ const r = raw && typeof raw === "object" ? raw : {};
2808
+ const provider = typeof r.provider === "string" ? r.provider.trim() : "";
2809
+ if (!provider) return null;
2810
+ const model = typeof r.model === "string" ? r.model.trim() : "";
2811
+ const thinkingLevel = typeof r.thinkingLevel === "string" ? r.thinkingLevel.trim() : "";
2812
+ const difficulty = Array.isArray(r.difficulty) ? r.difficulty.filter(isMeshTaskDifficulty) : [];
2813
+ const capability = Array.isArray(r.capability) ? r.capability.filter((t) => typeof t === "string" && !!t.trim()).map((t) => t.trim()) : [];
2814
+ const maxParallelNum = Number(r.maxParallel);
2815
+ const maxParallel = Number.isFinite(maxParallelNum) && maxParallelNum > 0 ? Math.floor(maxParallelNum) : void 0;
2816
+ return {
2817
+ provider,
2818
+ ...model ? { model } : {},
2819
+ ...thinkingLevel ? { thinkingLevel } : {},
2820
+ ...difficulty.length ? { difficulty } : {},
2821
+ ...capability.length ? { capability } : {},
2822
+ ...maxParallel !== void 0 ? { maxParallel } : {}
2823
+ };
2824
+ }
2825
+ function normalizeNodeCapabilitySlots(raw) {
2826
+ if (!Array.isArray(raw)) return [];
2827
+ const out = [];
2828
+ for (const entry of raw) {
2829
+ const slot = normalizeNodeCapabilitySlot(entry);
2830
+ if (slot) out.push(slot);
2831
+ }
2832
+ return out;
2833
+ }
2834
+ function deriveSlotsFromLegacy(input) {
2835
+ const priority = Array.isArray(input.providerPriority) ? input.providerPriority.filter((p) => typeof p === "string" && !!p.trim()).map((p) => p.trim()) : [];
2836
+ if (priority.length === 0) return [];
2837
+ const roleCap = /* @__PURE__ */ new Map();
2838
+ for (const role of input.providerRoles || []) {
2839
+ if (role && typeof role.providerType === "string" && Number.isFinite(role.maxParallel)) {
2840
+ roleCap.set(role.providerType.trim(), Math.floor(Number(role.maxParallel)));
2841
+ }
2842
+ }
2843
+ const brains = input.difficultyBrains || {};
2844
+ const byProvider = /* @__PURE__ */ new Map();
2845
+ const shared = [];
2846
+ for (const diff of MESH_TASK_DIFFICULTIES) {
2847
+ const b = brains[diff];
2848
+ if (!b) continue;
2849
+ const entry = { difficulty: diff, model: b.model, thinkingLevel: b.thinkingLevel };
2850
+ if (b.provider) {
2851
+ const list = byProvider.get(b.provider) ?? [];
2852
+ list.push(entry);
2853
+ byProvider.set(b.provider, list);
2854
+ } else {
2855
+ shared.push(entry);
2856
+ }
2857
+ }
2858
+ return priority.map((provider) => {
2859
+ const specific = byProvider.get(provider) || [];
2860
+ const applied = specific.length ? specific : shared;
2861
+ const difficulty = applied.map((a) => a.difficulty);
2862
+ const model = applied.find((a) => a.model)?.model;
2863
+ const thinkingLevel = applied.find((a) => a.thinkingLevel)?.thinkingLevel;
2864
+ const maxParallel = roleCap.get(provider);
2865
+ return {
2866
+ provider,
2867
+ ...model ? { model } : {},
2868
+ ...thinkingLevel ? { thinkingLevel } : {},
2869
+ ...difficulty.length ? { difficulty } : {},
2870
+ ...maxParallel !== void 0 ? { maxParallel } : {}
2871
+ };
2872
+ });
2873
+ }
2801
2874
  var DAEMON_ID_PREFIXES, MAGI_RAW_ANSWER_CAP, MESH_TASK_DIFFICULTIES, DEFAULT_DIFFICULTY_BRAINS, CANONICAL_MESH_TOOL_NAMES, CANONICAL_MESH_TOOL_COUNT;
2802
2875
  var init_dist = __esm({
2803
2876
  "../mesh-shared/dist/index.mjs"() {
@@ -2853,7 +2926,9 @@ var init_dist = __esm({
2853
2926
  "mesh_magi_review",
2854
2927
  "mesh_magi_collect",
2855
2928
  "mesh_magi_kind_panel_set",
2856
- "mesh_magi_kind_panel_list"
2929
+ "mesh_magi_kind_panel_list",
2930
+ "mesh_node_slots_set",
2931
+ "mesh_node_slots_list"
2857
2932
  ];
2858
2933
  CANONICAL_MESH_TOOL_COUNT = CANONICAL_MESH_TOOL_NAMES.length;
2859
2934
  }
@@ -3802,6 +3877,7 @@ function buildRulesSection(coordinatorCliType) {
3802
3877
  - **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.
3803
3878
  - **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
3879
  - **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.
3880
+ - **Retune node profiles when routing is a poor fit \u2014 but only with approval.** A node's capability slots (its provider/model/thinking + difficulty range + capability tags, seen via \`mesh_node_slots_list\`) are what task\u2192node fitness routing matches against. If you notice a persistent mismatch \u2014 e.g. every \`difficult\` task lands on a node whose only slot is a cheap model, or a capability a node clearly has isn't declared \u2014 you MAY propose a slot change with \`mesh_node_slots_set\` (write=false). That returns current-vs-proposed; present that diff to the user with a one-line reason and apply (write=true) ONLY after they approve. It is a WHOLESALE replacement of the node's slots, so include the slots you want to keep. Never rewrite a node's profile silently or without a clear routing reason.
3805
3881
  - **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.
3806
3882
  - **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
3807
3883
  - **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).
@@ -3882,7 +3958,9 @@ var init_coordinator_prompt = __esm({
3882
3958
  | \`mesh_magi_review\` | Cross-verify a read-only investigation across a standing panel of independent mesh agents (different machines/providers) instead of a single worker |
3883
3959
  | \`mesh_magi_collect\` | Collect + synthesize a previously dispatched MAGI fan-out by its consensus group id (async companion to mesh_magi_review wait:false) |
3884
3960
  | \`mesh_magi_kind_panel_set\` | Bind a task_kind \u2192 MAGI kind-panel slots (the SOLE MAGI panel-resolution surface; machine-local, wholesale replacement \u2014 approve current-vs-new first) |
3885
- | \`mesh_magi_kind_panel_list\` | List configured task_kind \u2192 MAGI kind-panel slot bindings (machine-local, read-only) |`;
3961
+ | \`mesh_magi_kind_panel_list\` | List configured task_kind \u2192 MAGI kind-panel slot bindings (machine-local, read-only) |
3962
+ | \`mesh_node_slots_list\` | List a node's capability slots (its AI-tool profile: provider/model/thinking + difficulty range + capability tags), read-only |
3963
+ | \`mesh_node_slots_set\` | PROPOSE (dry-run) or APPLY a node's capability slots \u2014 how you autonomously retune a node's tool profile; WHOLESALE replacement, present current-vs-proposed and get user approval before write=true |`;
3886
3964
  TOOL_EXPOSURE_PREFLIGHT_SECTION = `## Tool Exposure Preflight
3887
3965
 
3888
3966
  Before doing any coordinator work, confirm that the actual callable tool list includes \`mesh_status\` and the other \`mesh_*\` tools from the table above. If this Repo Mesh coordinator prompt is present but the callable \`mesh_*\` tools are missing, the MCP server/tool manifest is stale or not injected yet. Do not substitute terminal/file/git tools, do not inspect or edit the repository directly, and do not continue as a non-mesh local coding agent. Stop immediately and tell the user to run \`/reload-mcp\` or start a fresh coordinator session so ADHDev can reconnect \`adhdev-mesh\`.`;
@@ -5830,6 +5908,7 @@ function enqueueTask(meshId, message, opts) {
5830
5908
  const maxRetries = typeof opts?.maxRetries === "number" && Number.isFinite(opts.maxRetries) && opts.maxRetries >= 0 ? Math.floor(opts.maxRetries) : void 0;
5831
5909
  let effectiveModel = typeof opts?.model === "string" && opts.model.trim() ? opts.model.trim() : void 0;
5832
5910
  let effectiveThinkingLevel = typeof opts?.thinkingLevel === "string" && opts.thinkingLevel.trim() ? opts.thinkingLevel.trim() : void 0;
5911
+ const taskDifficulty = isMeshTaskDifficulty(opts?.difficulty) ? opts.difficulty : void 0;
5833
5912
  if (isMeshTaskDifficulty(opts?.difficulty)) {
5834
5913
  try {
5835
5914
  const preset = getDifficultyBrains()[opts.difficulty];
@@ -5873,6 +5952,7 @@ function enqueueTask(meshId, message, opts) {
5873
5952
  ...typeof opts?.consensusGroupId === "string" && opts.consensusGroupId.trim() ? { consensusGroupId: opts.consensusGroupId.trim() } : {},
5874
5953
  ...effectiveModel ? { model: effectiveModel } : {},
5875
5954
  ...effectiveThinkingLevel ? { thinkingLevel: effectiveThinkingLevel } : {},
5955
+ ...taskDifficulty ? { difficulty: taskDifficulty } : {},
5876
5956
  ...typeof opts?.sourceCoordinatorSessionId === "string" && opts.sourceCoordinatorSessionId.trim() ? { sourceCoordinatorSessionId: opts.sourceCoordinatorSessionId.trim() } : {},
5877
5957
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
5878
5958
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -15862,8 +15942,16 @@ function nodeHasActiveAssignment(meshId, nodeId) {
15862
15942
  function nodeActiveLoad(meshId, nodeId) {
15863
15943
  return MeshRuntimeStore.getInstance().nodeActiveAssignmentCount(meshId, nodeId);
15864
15944
  }
15945
+ function meshHasExplicitSlots(mesh) {
15946
+ const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
15947
+ return nodes.some((n) => normalizeNodeCapabilitySlots(n?.policy?.slots).length > 0);
15948
+ }
15865
15949
  function resolveSchedulingStrategy(mesh) {
15866
- return normalizeMeshSchedulingStrategy(mesh?.policy?.schedulingStrategy);
15950
+ const raw = mesh?.policy?.schedulingStrategy;
15951
+ if (typeof raw === "string" && raw.trim()) {
15952
+ return normalizeMeshSchedulingStrategy(raw);
15953
+ }
15954
+ return meshHasExplicitSlots(mesh) ? "fitness" : normalizeMeshSchedulingStrategy(void 0);
15867
15955
  }
15868
15956
  function buildSchedulingPool(localCandidates, remoteCandidates) {
15869
15957
  const pool = [...localCandidates, ...remoteCandidates].map((c) => ({
@@ -15877,10 +15965,68 @@ function buildSchedulingPool(localCandidates, remoteCandidates) {
15877
15965
  }));
15878
15966
  return { pool, uniqueNodes };
15879
15967
  }
15968
+ function resolveNodeCapabilitySlots(node) {
15969
+ const explicit = normalizeNodeCapabilitySlots(node?.policy?.slots);
15970
+ if (explicit.length) return explicit;
15971
+ let difficultyBrains;
15972
+ try {
15973
+ difficultyBrains = getDifficultyBrains();
15974
+ } catch {
15975
+ difficultyBrains = void 0;
15976
+ }
15977
+ return deriveSlotsFromLegacy({
15978
+ providerPriority: normalizeProviderPriority(node?.policy),
15979
+ providerRoles: Array.isArray(node?.policy?.providerRoles) ? node.policy.providerRoles : void 0,
15980
+ difficultyBrains
15981
+ });
15982
+ }
15983
+ function scoreSlotForTask(slot, task) {
15984
+ let score = 1;
15985
+ const diff = isMeshTaskDifficulty(task.difficulty) ? task.difficulty : void 0;
15986
+ if (diff) {
15987
+ if (slot.difficulty?.length) {
15988
+ score += slot.difficulty.includes(diff) ? 100 : 0;
15989
+ } else {
15990
+ score += 20;
15991
+ }
15992
+ }
15993
+ const req = task.requiredTags?.filter((t) => !!t) ?? [];
15994
+ if (req.length) {
15995
+ const cap = new Set(slot.capability ?? []);
15996
+ const covered = req.every((t) => cap.has(t));
15997
+ score += covered ? 30 : 0;
15998
+ }
15999
+ return score;
16000
+ }
16001
+ function bestSlotForTask(node, task) {
16002
+ const slots = resolveNodeCapabilitySlots(node);
16003
+ if (!slots.length) return null;
16004
+ let best = null;
16005
+ for (const slot of slots) {
16006
+ const score = scoreSlotForTask(slot, task);
16007
+ if (!best || score > best.score) best = { slot, score };
16008
+ }
16009
+ return best;
16010
+ }
16011
+ function nodeFitnessForTask(node, task) {
16012
+ return bestSlotForTask(node, task)?.score ?? 0;
16013
+ }
15880
16014
  function orderEligibleNodes(meshId, strategy, nodes, opts) {
15881
16015
  if (strategy === "first_eligible" || nodes.length <= 1) {
15882
16016
  return nodes;
15883
16017
  }
16018
+ if (strategy === "fitness" && opts?.task) {
16019
+ const task = opts.task;
16020
+ return [...nodes].sort((a, b) => {
16021
+ const fitDelta = nodeFitnessForTask(b.node, task) - nodeFitnessForTask(a.node, task);
16022
+ if (fitDelta !== 0) return fitDelta;
16023
+ const prioDelta = resolveNodeSchedulingPriority(b.node?.policy) - resolveNodeSchedulingPriority(a.node?.policy);
16024
+ if (prioDelta !== 0) return prioDelta;
16025
+ const loadDelta = nodeActiveLoad(meshId, a.nodeId) - nodeActiveLoad(meshId, b.nodeId);
16026
+ if (loadDelta !== 0) return loadDelta;
16027
+ return a.index - b.index;
16028
+ });
16029
+ }
15884
16030
  const priorityOf = (n) => resolveNodeSchedulingPriority(n.node?.policy);
15885
16031
  let rotation = 0;
15886
16032
  if (strategy === "least_loaded" || strategy === "round_robin") {
@@ -16024,13 +16170,15 @@ function markAutoLaunch(meshId, taskId, args) {
16024
16170
  retractActionableSkipIfPreviouslyNotified(meshId, taskId);
16025
16171
  }
16026
16172
  }
16027
- async function resolveUsableProvider(components, nodeId, node, requiredTags) {
16028
- const providerPriority = normalizeProviderPriority(node?.policy);
16029
- if (!providerPriority.length) return { reason: "missing_provider_priority" };
16173
+ async function resolveUsableProvider(components, nodeId, node, requiredTags, task) {
16030
16174
  const providerLoader = components.providerLoader;
16031
16175
  if (!providerLoader) return { reason: "provider_loader_unavailable" };
16176
+ const slots = resolveNodeCapabilitySlots(node);
16177
+ if (!slots.length) return { reason: "missing_provider_priority" };
16178
+ const orderedSlots = task ? [...slots].sort((a, b) => scoreSlotForTask(b, task) - scoreSlotForTask(a, task)) : slots;
16032
16179
  const failed = [];
16033
- for (const requestedType of providerPriority) {
16180
+ for (const slot of orderedSlots) {
16181
+ const requestedType = slot.provider;
16034
16182
  const normalizedType = typeof providerLoader.resolveAlias === "function" ? providerLoader.resolveAlias(requestedType) : requestedType;
16035
16183
  if (requiredTags?.length && !nodeSatisfiesRequiredTags(requiredTags, buildMeshNodeCapabilityTags(node, normalizedType))) {
16036
16184
  failed.push(`${requestedType}: required_tags_mismatch`);
@@ -16055,7 +16203,13 @@ async function resolveUsableProvider(components, nodeId, node, requiredTags) {
16055
16203
  }], false);
16056
16204
  }
16057
16205
  components.onStatusChange?.();
16058
- if (detected) return { providerType: normalizedType };
16206
+ if (detected) {
16207
+ return {
16208
+ providerType: normalizedType,
16209
+ ...slot.model ? { model: slot.model } : {},
16210
+ ...slot.thinkingLevel ? { thinkingLevel: slot.thinkingLevel } : {}
16211
+ };
16212
+ }
16059
16213
  failed.push(`${requestedType}: not detected`);
16060
16214
  }
16061
16215
  return { reason: `provider_priority_unusable: ${failed.join("; ") || nodeId}` };
@@ -16183,7 +16337,9 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
16183
16337
  meshId,
16184
16338
  strategy,
16185
16339
  candidateNodes.map((node, index) => ({ nodeId: readMeshNodeId(node), node, index })).filter((c) => c.nodeId),
16186
- { bumpCursor: true }
16340
+ // Auto-launch drains one task at a time, so the task IS in scope here —
16341
+ // pass it through for the 'fitness' strategy's task→slot ranking.
16342
+ { bumpCursor: true, task: { difficulty: task.difficulty, requiredTags: task.requiredTags } }
16187
16343
  ).map((c) => c.node);
16188
16344
  for (const node of orderedCandidateNodes) {
16189
16345
  const nodeId = readMeshNodeId(node);
@@ -16230,11 +16386,13 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
16230
16386
  }
16231
16387
  autoLaunchInProgress.add(launchKey);
16232
16388
  try {
16233
- const resolved = await resolveUsableProvider(components, nodeId, node, task.requiredTags);
16389
+ const resolved = await resolveUsableProvider(components, nodeId, node, task.requiredTags, { difficulty: task.difficulty, requiredTags: task.requiredTags });
16234
16390
  if (!resolved.providerType) {
16235
16391
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: resolved.reason || "provider_unusable", nodeId });
16236
16392
  continue;
16237
16393
  }
16394
+ const effectiveModel = typeof task.model === "string" && task.model.trim() ? task.model.trim() : resolved.model;
16395
+ const effectiveThinkingLevel = typeof task.thinkingLevel === "string" && task.thinkingLevel.trim() ? task.thinkingLevel.trim() : resolved.thinkingLevel;
16238
16396
  const providerCap = resolveProviderMaxParallel(node?.policy, resolved.providerType);
16239
16397
  if (providerCap !== void 0 && activeProviderAssignedCount(meshId, nodeId, resolved.providerType) >= providerCap) {
16240
16398
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_provider_parallel_reached", nodeId, providerType: resolved.providerType });
@@ -16268,9 +16426,10 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
16268
16426
  settings: remoteSettings,
16269
16427
  // MAGI-KIND-PANEL model axis: forward the task's model override so the
16270
16428
  // remote worker session launches with it (initialModel). Best-effort.
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() } : {}
16429
+ // Slot-aware: task override wins, else the matched slot's model.
16430
+ ...effectiveModel ? { initialModel: effectiveModel } : {},
16431
+ // BRAIN-ROUTING thinking axis: forward the effective thinking level (initialThinkingLevel).
16432
+ ...effectiveThinkingLevel ? { initialThinkingLevel: effectiveThinkingLevel } : {}
16274
16433
  });
16275
16434
  } catch (e) {
16276
16435
  markAutoLaunch(meshId, task.id, { status: "failed", reason: `remote_launch_dispatch_failed: ${e?.message || String(e)}`, nodeId, providerType: resolved.providerType });
@@ -16297,11 +16456,11 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
16297
16456
  cliType: resolved.providerType,
16298
16457
  dir: node.workspace,
16299
16458
  settings: launchSettings,
16300
- // MAGI-KIND-PANEL model axis: local launch forwards the task's model
16301
- // override as initialModel (CLI → modelLaunchArgs; ACP → setConfigOption).
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() } : {}
16459
+ // MAGI-KIND-PANEL model axis: local launch forwards the effective model
16460
+ // (task override, else matched slot) as initialModel (CLI → modelLaunchArgs; ACP → setConfigOption).
16461
+ ...effectiveModel ? { initialModel: effectiveModel } : {},
16462
+ // BRAIN-ROUTING thinking axis: forward the effective thinking level (initialThinkingLevel).
16463
+ ...effectiveThinkingLevel ? { initialThinkingLevel: effectiveThinkingLevel } : {}
16305
16464
  });
16306
16465
  if (!launchResult?.success) {
16307
16466
  const reason = launchResult?.error || "launch_cli_failed";
@@ -16436,7 +16595,7 @@ async function triggerMeshQueue(components, meshId) {
16436
16595
  const aPrio = resolveNodeSchedulingPriority(a.node?.policy);
16437
16596
  const bPrio = resolveNodeSchedulingPriority(b.node?.policy);
16438
16597
  if (aPrio !== bPrio) return bPrio - aPrio;
16439
- if (strategy === "least_loaded" || strategy === "round_robin") {
16598
+ if (strategy === "least_loaded" || strategy === "round_robin" || strategy === "fitness") {
16440
16599
  const loadDelta = nodeActiveLoad(meshId, a.nodeId) - nodeActiveLoad(meshId, b.nodeId);
16441
16600
  if (loadDelta !== 0) return loadDelta;
16442
16601
  }
@@ -18431,6 +18590,22 @@ var init_provider_input_support = __esm({
18431
18590
  });
18432
18591
 
18433
18592
  // src/status/builders.ts
18593
+ function isCoordinatorSpawnedHiddenWorker(settings) {
18594
+ if (!settings) return false;
18595
+ return settings.launchedByCoordinator === true && typeof settings.meshNodeFor === "string" && settings.meshNodeFor.trim().length > 0 && settings.spawnedSessionVisibility === "hidden";
18596
+ }
18597
+ function resolveSurfaceHidden(settings) {
18598
+ if (!settings) return false;
18599
+ if (settings.userHidden === true) return true;
18600
+ if (settings.userHidden === false) return false;
18601
+ return settings.spawnedSessionVisibility === "hidden" || isCoordinatorSpawnedHiddenWorker(settings);
18602
+ }
18603
+ function resolveMuted(settings) {
18604
+ if (!settings) return false;
18605
+ if (settings.userMuted === true) return true;
18606
+ if (settings.userMuted === false) return false;
18607
+ return isCoordinatorSpawnedHiddenWorker(settings);
18608
+ }
18434
18609
  function getActiveChatOptions(profile) {
18435
18610
  if (profile === "full") return {};
18436
18611
  return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
@@ -18636,7 +18811,8 @@ function buildCliSession(state, options) {
18636
18811
  settings: state.settings,
18637
18812
  ...coordinator && { coordinator },
18638
18813
  ...meshQueueStats && { meshQueueStats },
18639
- ...state.settings?.spawnedSessionVisibility === "hidden" && { surfaceHidden: true }
18814
+ ...resolveSurfaceHidden(state.settings) && { surfaceHidden: true },
18815
+ ...resolveMuted(state.settings) && { muted: true }
18640
18816
  };
18641
18817
  }
18642
18818
  function buildAcpSession(state, options) {
@@ -18677,7 +18853,8 @@ function buildAcpSession(state, options) {
18677
18853
  settings: state.settings,
18678
18854
  ...coordinator && { coordinator },
18679
18855
  ...meshQueueStats && { meshQueueStats },
18680
- ...state.settings?.spawnedSessionVisibility === "hidden" && { surfaceHidden: true }
18856
+ ...resolveSurfaceHidden(state.settings) && { surfaceHidden: true },
18857
+ ...resolveMuted(state.settings) && { muted: true }
18681
18858
  };
18682
18859
  }
18683
18860
  function buildSessionEntries(allStates, cdpManagers, options = {}) {
@@ -27639,6 +27816,7 @@ __export(index_exports, {
27639
27816
  appendRemoteLedgerEntries: () => appendRemoteLedgerEntries,
27640
27817
  assertNoDependencyCycle: () => assertNoDependencyCycle,
27641
27818
  buildAssistantChatMessage: () => buildAssistantChatMessage,
27819
+ buildAvailableProviders: () => buildAvailableProviders,
27642
27820
  buildChatMessage: () => buildChatMessage,
27643
27821
  buildChatMessageSignature: () => buildChatMessageSignature,
27644
27822
  buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
@@ -39497,11 +39675,15 @@ ${formatManifestValidationIssues2(validation.issues)}`,
39497
39675
  if (!manifestPath) continue;
39498
39676
  try {
39499
39677
  const m = JSON.parse(fs41.readFileSync(manifestPath, "utf-8"));
39678
+ const modelOptions = Array.isArray(m.modelOptions) ? m.modelOptions.filter((x) => typeof x === "string" && !!x.trim()) : [];
39679
+ const thinkingLevelOptions = Array.isArray(m.thinkingLevelOptions) ? m.thinkingLevelOptions.filter((x) => typeof x === "string" && !!x.trim()) : [];
39500
39680
  items.push({
39501
39681
  type,
39502
39682
  category,
39503
39683
  version: typeof m.providerVersion === "string" ? m.providerVersion : "0.0.0",
39504
- path: manifestPath
39684
+ path: manifestPath,
39685
+ ...modelOptions.length ? { modelOptions } : {},
39686
+ ...thinkingLevelOptions.length ? { thinkingLevelOptions } : {}
39505
39687
  });
39506
39688
  } catch {
39507
39689
  }
@@ -50285,6 +50467,31 @@ var cliAgentHandlers = {
50285
50467
  record_provider_pty: async (ctx, args) => {
50286
50468
  return ctx.deps.cliManager.handleCliCommand("record_provider_pty", args);
50287
50469
  },
50470
+ // Daemon-owned per-session user Mute/Hide. Replaces the old browser-local
50471
+ // localStorage layer: the user's manual hide/mute for a conversation is stored
50472
+ // in-memory on the live session's settings (userHidden / userMuted) and rides
50473
+ // the SAME status snapshot pipeline as the coordinator-policy surfaceHidden
50474
+ // flag, so every client of this daemon sees the same state. In-memory only —
50475
+ // resets on daemon restart (coordinator-spawned sessions re-derive their hidden
50476
+ // default from mesh policy on relaunch). Passing null/undefined for a field
50477
+ // leaves it unchanged; pass an explicit boolean to set, or false to clear an
50478
+ // earlier hide/mute (e.g. unmute a coordinator-spawned worker overrides the
50479
+ // policy default until restart).
50480
+ set_conversation_prefs: async (ctx, args) => {
50481
+ const sessionId = readStringValue(args?.sessionId, args?.targetSessionId, args?.instanceId);
50482
+ if (!sessionId) return { success: false, error: "sessionId required" };
50483
+ const inst = ctx.deps.instanceManager.getInstance(sessionId);
50484
+ if (!inst || typeof inst.updateSettings !== "function") {
50485
+ return { success: false, error: "Session not found or does not support preferences" };
50486
+ }
50487
+ const patch = {};
50488
+ if (typeof args?.hidden === "boolean") patch.userHidden = args.hidden;
50489
+ if (typeof args?.muted === "boolean") patch.userMuted = args.muted;
50490
+ if (!Object.keys(patch).length) return { success: false, error: "Nothing to update (hidden and/or muted required)" };
50491
+ inst.updateSettings(patch);
50492
+ ctx.deps.onStatusChange?.();
50493
+ return { success: true, sessionId, ...patch };
50494
+ },
50288
50495
  agent_command: async (ctx, args) => {
50289
50496
  {
50290
50497
  const dispatchSessionId = readStringValue(args?.targetSessionId, args?.sessionId, args?.instanceId);
@@ -56546,6 +56753,8 @@ var meshCoordinatorLaunchHandlers = {
56546
56753
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
56547
56754
  let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
56548
56755
  const extraSystemPrompt = typeof args?.extraSystemPrompt === "string" ? args.extraSystemPrompt.trim() : "";
56756
+ const initialModel = typeof args?.initialModel === "string" && args.initialModel.trim() ? args.initialModel.trim() : null;
56757
+ const initialThinkingLevel = typeof args?.initialThinkingLevel === "string" && args.initialThinkingLevel.trim() ? args.initialThinkingLevel.trim() : null;
56549
56758
  if (!meshId) return { success: false, error: "meshId required" };
56550
56759
  try {
56551
56760
  const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
@@ -56816,7 +57025,9 @@ ${ptyResult.output.slice(-2e3)}`);
56816
57025
  dir: workspace,
56817
57026
  cliArgs: cliCmdArgs.length > 0 ? cliCmdArgs : void 0,
56818
57027
  env: Object.keys(cliCmdEnv).length > 0 ? cliCmdEnv : void 0,
56819
- settings: { meshCoordinatorFor: meshId }
57028
+ settings: { meshCoordinatorFor: meshId },
57029
+ ...initialModel ? { initialModel } : {},
57030
+ ...initialThinkingLevel ? { initialThinkingLevel } : {}
56820
57031
  });
56821
57032
  if (cliCmdLaunch?.success && cliCmdContextFilePath) {
56822
57033
  const stripPath = cliCmdContextFilePath;
@@ -57001,7 +57212,9 @@ ${ptyResult.output.slice(-2e3)}`);
57001
57212
  env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
57002
57213
  settings: {
57003
57214
  meshCoordinatorFor: meshId
57004
- }
57215
+ },
57216
+ ...initialModel ? { initialModel } : {},
57217
+ ...initialThinkingLevel ? { initialThinkingLevel } : {}
57005
57218
  });
57006
57219
  if (launchResult?.success && autoImportContextFilePath) {
57007
57220
  const stripPath = autoImportContextFilePath;
@@ -57360,6 +57573,11 @@ var meshStatusHandlers = {
57360
57573
  ...node.reportedProviderVersions && typeof node.reportedProviderVersions === "object" ? { providerVersions: node.reportedProviderVersions } : {},
57361
57574
  ...typeof node.reportedDaemonBuildVersion === "string" && node.reportedDaemonBuildVersion ? { daemonBuildVersion: node.reportedDaemonBuildVersion } : {},
57362
57575
  providerPriority,
57576
+ // ORCHESTRATION_NODE_SLOTS.md: surface the node's capability
57577
+ // slots so the dashboard slot editor can read them. Only
57578
+ // emitted when explicitly configured (derived-from-legacy
57579
+ // slots stay implicit — the editor shows the legacy fields).
57580
+ ...Array.isArray(node.policy?.slots) && node.policy.slots.length ? { slots: normalizeNodeCapabilitySlots(node.policy.slots) } : {},
57363
57581
  activeSessions: [],
57364
57582
  activeSessionDetails: [],
57365
57583
  launchReady: false
@@ -70224,6 +70442,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
70224
70442
  appendRemoteLedgerEntries,
70225
70443
  assertNoDependencyCycle,
70226
70444
  buildAssistantChatMessage,
70445
+ buildAvailableProviders,
70227
70446
  buildChatMessage,
70228
70447
  buildChatMessageSignature,
70229
70448
  buildChatTailDeliverySignature,