@adhdev/daemon-standalone 1.0.28 → 1.0.29-rc.10

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/public/index.html CHANGED
@@ -7,9 +7,9 @@
7
7
  <meta name="description" content="ADHDev self-hosted dashboard for controlling AI agents" />
8
8
  <link rel="icon" href="/otter-logo.png" />
9
9
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />
10
- <script type="module" crossorigin src="/assets/index-Dm68eVOH.js"></script>
11
- <link rel="modulepreload" crossorigin href="/assets/vendor-cL4V2vaO.js">
12
- <link rel="stylesheet" crossorigin href="/assets/index-Jy4W-yh-.css">
10
+ <script type="module" crossorigin src="/assets/index-CKyjF8wa.js"></script>
11
+ <link rel="modulepreload" crossorigin href="/assets/vendor-DyCWA2YZ.js">
12
+ <link rel="stylesheet" crossorigin href="/assets/index-DaANjDZS.css">
13
13
  </head>
14
14
  <body>
15
15
  <!-- Apply theme immediately to prevent FOIT (Flash of Incorrect Theme) -->
@@ -1544,7 +1544,7 @@ var MESH_MAGI_COLLECT_TOOL = {
1544
1544
  };
1545
1545
  var MESH_MAGI_KIND_PANEL_SET_TOOL = {
1546
1546
  name: "mesh_magi_kind_panel_set",
1547
- description: "Bind a task_kind to its MAGI kind-panel slot list (machine-local ~/.adhdev/meshes.json `magiKindPanels`). This binding is what a `mesh_magi_review({ task_kind })` resolves to \u2014 it is the SOLE panel-resolution path (there is no named-panel or inline-members alternative). IMPORTANT \u2014 WHOLESALE REPLACEMENT: a task_kind has exactly one binding, so the `slots` you pass become the COMPLETE new slot set and any prior slots for that kind are dropped (not merged). Because it silently replaces the current binding, get EXPLICIT user approval before writing and present the current-vs-new slot lists (the dry-run returns `currentSlots`). Defaults to dry-run (write=false). Machine-local scope (NOT a repo-committed file).",
1547
+ description: "Bind a task_kind to its MAGI kind-panel slot list for THIS mesh (machine-local ~/.adhdev/meshes.json \u2192 `meshes[].magiKindPanels`). This binding is what a `mesh_magi_review({ task_kind })` resolves to \u2014 it is the SOLE panel-resolution path (there is no named-panel or inline-members alternative). SCOPE: PER MESH, stored machine-locally (NOT a repo-committed file). The write targets the calling coordinator's mesh only; another mesh on the same machine keeps its own independent binding for the same task_kind. IMPORTANT \u2014 WHOLESALE REPLACEMENT: a task_kind has exactly one binding per mesh, so the `slots` you pass become the COMPLETE new slot set and any prior slots for that kind are dropped (not merged). Because it silently replaces the current binding, get EXPLICIT user approval before writing and present the current-vs-new slot lists (the dry-run returns `currentSlots`). Defaults to dry-run (write=false). A slot's `nodeId`, when given, MUST name a node of this mesh \u2014 a foreign or unknown node id is rejected (invalid_magi_kind_panel).",
1548
1548
  inputSchema: {
1549
1549
  type: "object",
1550
1550
  properties: {
@@ -1556,7 +1556,7 @@ var MESH_MAGI_KIND_PANEL_SET_TOOL = {
1556
1556
  type: "object",
1557
1557
  properties: {
1558
1558
  provider: { type: "string", description: "REQUIRED \u2014 provider type, e.g. claude-cli / codex-cli / gemini-cli / hermes-cli." },
1559
- nodeId: { type: "string", description: "Optional \u2014 pin to a specific mesh node id." },
1559
+ nodeId: { type: "string", description: "Optional \u2014 pin to a specific node OF THIS MESH (validated against the mesh node list; a node id from another mesh is rejected). Omit to let the fan-out pick any node offering the provider." },
1560
1560
  model: { type: "string", description: "Optional \u2014 pin a specific model for this slot." },
1561
1561
  capabilityTags: { type: "array", items: { type: "string" }, description: "Optional routing tags (ANDed with the provider tag) when nodeId is absent." },
1562
1562
  n: { type: "number", description: "Optional per-slot replica count (default 1)." }
@@ -1571,7 +1571,7 @@ var MESH_MAGI_KIND_PANEL_SET_TOOL = {
1571
1571
  };
1572
1572
  var MESH_MAGI_KIND_PANEL_LIST_TOOL = {
1573
1573
  name: "mesh_magi_kind_panel_list",
1574
- description: "List the configured MAGI kind\u2192panel slot bindings (machine-local). Read-only. Use to confirm what a `task_kind` resolves to before mesh_magi_review, and to diff current-vs-new before an overwrite via mesh_magi_kind_panel_set.",
1574
+ description: "List the MAGI kind\u2192panel slot bindings configured for THIS mesh (machine-local, per mesh). Read-only. The response `scope` names the mesh the bindings belong to \u2014 panels are per mesh, so another mesh on this machine has its own independent set. Use to confirm what a `task_kind` resolves to before mesh_magi_review, and to diff current-vs-new before an overwrite via mesh_magi_kind_panel_set.",
1575
1575
  inputSchema: {
1576
1576
  type: "object",
1577
1577
  properties: {
@@ -5618,31 +5618,42 @@ function replicaCompletionIsWeak(meshId, taskId) {
5618
5618
  }
5619
5619
  return false;
5620
5620
  }
5621
+ function magiPanelScope(meshId, meshName) {
5622
+ return {
5623
+ kind: "mesh",
5624
+ storage: "machine_local",
5625
+ meshId,
5626
+ ...meshName ? { meshName } : {},
5627
+ note: "Kind-panels are per mesh, stored machine-locally (not repo-committed). Another mesh on this machine has its own independent bindings."
5628
+ };
5629
+ }
5621
5630
  async function meshMagiKindPanelSet(ctx, args) {
5622
5631
  const kind = readString(args.task_kind) || readString(args.kind);
5623
5632
  if (!kind) return JSON.stringify({ success: false, error: "task_kind required" });
5624
5633
  const write = args.write === true;
5634
+ const meshId = ctx.mesh.id;
5635
+ const scope = magiPanelScope(meshId, ctx.mesh.name);
5625
5636
  try {
5626
- const current = (0, import_daemon_core4.getMagiKindPanel)(kind) ?? [];
5637
+ const current = (0, import_daemon_core4.getMagiKindPanel)(kind, meshId) ?? [];
5627
5638
  if (!write) {
5628
- const preview = (0, import_daemon_core4.normalizeMagiSlots)(args.slots);
5639
+ const preview = (0, import_daemon_core4.normalizeMagiSlots)(args.slots, ctx.mesh.nodes.map((n) => n.id));
5629
5640
  return JSON.stringify({
5630
5641
  success: true,
5631
5642
  dryRun: true,
5632
5643
  taskKind: kind,
5633
- scope: "machine_local",
5644
+ scope,
5634
5645
  replacement: true,
5635
5646
  currentSlots: current,
5636
5647
  slots: preview,
5637
- note: "Dry-run only \u2014 no file written. This is a WHOLESALE replacement of the kind's slot list (machine-local ~/.adhdev/meshes.json); the currentSlots would be fully replaced. Re-run with write=true after explicit user approval."
5648
+ note: `Dry-run only \u2014 no file written. This is a WHOLESALE replacement of the kind's slot list for mesh '${meshId}' (machine-local ~/.adhdev/meshes.json); the currentSlots would be fully replaced. Other meshes on this machine are unaffected. Re-run with write=true after explicit user approval.`
5638
5649
  }, null, 2);
5639
5650
  }
5640
- const slots = (0, import_daemon_core4.setMagiKindPanel)(kind, args.slots);
5651
+ const slots = (0, import_daemon_core4.setMagiKindPanel)(kind, args.slots, meshId);
5641
5652
  return JSON.stringify({
5642
5653
  success: true,
5643
5654
  written: true,
5644
5655
  taskKind: kind,
5645
- scope: "machine_local",
5656
+ scope,
5646
5657
  replacement: true,
5647
5658
  previousSlots: current,
5648
5659
  slots,
@@ -5651,25 +5662,28 @@ async function meshMagiKindPanelSet(ctx, args) {
5651
5662
  } catch (e) {
5652
5663
  const message = e?.message || String(e);
5653
5664
  const code = message.includes("invalid_magi_kind_panel") ? "invalid_magi_kind_panel" : void 0;
5654
- return JSON.stringify({ success: false, ...code ? { code } : {}, error: message });
5665
+ return JSON.stringify({ success: false, ...code ? { code } : {}, scope, error: message });
5655
5666
  }
5656
5667
  }
5657
5668
  async function meshMagiKindPanelList(ctx, args = {}) {
5658
5669
  const only = readString(args.task_kind) || readString(args.kind);
5659
- const all = (0, import_daemon_core4.listMagiKindPanels)();
5670
+ const meshId = ctx.mesh.id;
5671
+ const scope = magiPanelScope(meshId, ctx.mesh.name);
5672
+ const all = (0, import_daemon_core4.listMagiKindPanels)(meshId);
5660
5673
  if (only) {
5661
- const slots = (0, import_daemon_core4.getMagiKindPanel)(only);
5674
+ const slots = (0, import_daemon_core4.getMagiKindPanel)(only, meshId);
5662
5675
  if (slots === void 0) {
5663
5676
  return JSON.stringify({
5664
5677
  success: false,
5665
5678
  code: "magi_kind_not_configured",
5666
- error: `task_kind '${only}' has no configured kind-panel binding`,
5679
+ error: `task_kind '${only}' has no configured kind-panel binding in mesh '${meshId}'`,
5680
+ scope,
5667
5681
  configuredKinds: Object.keys(all)
5668
5682
  }, null, 2);
5669
5683
  }
5670
- return JSON.stringify({ success: true, scope: "machine_local", taskKind: only, slots }, null, 2);
5684
+ return JSON.stringify({ success: true, scope, taskKind: only, slots }, null, 2);
5671
5685
  }
5672
- return JSON.stringify({ success: true, scope: "machine_local", kindPanels: all, configuredKinds: Object.keys(all) }, null, 2);
5686
+ return JSON.stringify({ success: true, scope, kindPanels: all, configuredKinds: Object.keys(all) }, null, 2);
5673
5687
  }
5674
5688
  async function meshMagiReview(ctx, args) {
5675
5689
  const question = readString(args.question);
@@ -5690,14 +5704,15 @@ async function meshMagiReview(ctx, args) {
5690
5704
  const referenceSubmoduleKey = resolveMagiReferenceSubmoduleKey(ctx);
5691
5705
  const taskKind = normalizeMagiTaskKind(explicitTaskKind);
5692
5706
  const panelName = `(kind:${taskKind})`;
5693
- const slots = (0, import_daemon_core4.getMagiKindPanel)(taskKind);
5707
+ const slots = (0, import_daemon_core4.getMagiKindPanel)(taskKind, ctx.mesh.id);
5694
5708
  if (!slots || slots.length === 0) {
5695
5709
  return JSON.stringify({
5696
5710
  success: false,
5697
5711
  code: "magi_kind_not_configured",
5698
- error: `No panel slots are configured for this task_kind in mesh settings. Add at least one (machine + provider + model) slot in settings \u2014 task_kind '${taskKind}' has no configured kind-panel.`,
5712
+ error: `No panel slots are configured for this task_kind in mesh '${ctx.mesh.id}' settings. Add at least one (machine + provider + model) slot in settings \u2014 task_kind '${taskKind}' has no configured kind-panel.`,
5699
5713
  taskKind,
5700
- configuredKinds: Object.keys((0, import_daemon_core4.listMagiKindPanels)()),
5714
+ meshId: ctx.mesh.id,
5715
+ configuredKinds: Object.keys((0, import_daemon_core4.listMagiKindPanels)(ctx.mesh.id)),
5701
5716
  hint: "Configure this kind in mesh settings (MagiKindPanelEditor), or set it with mesh_magi_kind_panel_set, then retry."
5702
5717
  }, null, 2);
5703
5718
  }
@@ -5710,9 +5725,26 @@ async function meshMagiReview(ctx, args) {
5710
5725
  code: "invalid_magi_kind_panel",
5711
5726
  error: `configured kind-panel for '${taskKind}' is invalid: ${e?.message || String(e)}`,
5712
5727
  taskKind,
5728
+ meshId: ctx.mesh.id,
5713
5729
  hint: "Re-save the kind-panel slots in mesh settings \u2014 each slot needs a provider; nodeId / model are optional."
5714
5730
  }, null, 2);
5715
5731
  }
5732
+ const meshNodeIds = new Set(ctx.mesh.nodes.map((n) => n.id));
5733
+ const danglingSlots = planSlots.filter((s) => s.nodeId && !meshNodeIds.has(s.nodeId));
5734
+ if (danglingSlots.length) {
5735
+ planSlots = planSlots.filter((s) => !s.nodeId || meshNodeIds.has(s.nodeId));
5736
+ if (planSlots.length === 0) {
5737
+ return JSON.stringify({
5738
+ success: false,
5739
+ code: "magi_kind_panel_all_slots_dangling",
5740
+ error: `Every slot in kind-panel '${panelName}' is pinned to a node that is not in mesh '${ctx.mesh.id}' (${danglingSlots.map((s) => s.nodeId).join(", ")}).`,
5741
+ taskKind,
5742
+ meshId: ctx.mesh.id,
5743
+ danglingSlots,
5744
+ hint: "Re-bind this kind to nodes of THIS mesh with mesh_magi_kind_panel_set (or in mesh settings). Check mesh_status for the current node list."
5745
+ }, null, 2);
5746
+ }
5747
+ }
5716
5748
  const includeStale = (args.include_stale ?? args.includeStale) === true;
5717
5749
  const plan = buildMagiFanoutPlan(planSlots, ctx.mesh.nodes, { n: args.n, referenceCommit, referenceSubmoduleKey, includeStale });
5718
5750
  if (!plan.enoughTargets) {
@@ -5729,6 +5761,10 @@ async function meshMagiReview(ctx, args) {
5729
5761
  unavailableSlots: plan.unavailableSlots,
5730
5762
  ...droppedByHealth ? { unhealthySlots: plan.unhealthySlots } : {},
5731
5763
  ...droppedByStale ? { staleSlots: plan.staleSlots } : {},
5764
+ // Surface slots dropped for naming a node outside this mesh, so an
5765
+ // under-quorum panel caused by a stale pin is diagnosable rather than
5766
+ // looking like a mis-sized panel.
5767
+ ...danglingSlots.length ? { danglingSlots } : {},
5732
5768
  hint
5733
5769
  }, null, 2);
5734
5770
  }
@@ -7894,6 +7930,7 @@ async function meshRefineNode(ctx, args) {
7894
7930
  ...args.execute !== void 0 ? { execute: args.execute } : {},
7895
7931
  ...args.dry_run !== void 0 ? { dryRun: args.dry_run } : {},
7896
7932
  ...coordinatorDaemonId ? { coordinatorDaemonId } : {},
7933
+ ...ctx.coordinatorSessionId ? { coordinatorSessionId: ctx.coordinatorSessionId } : {},
7897
7934
  inlineMesh: ctx.mesh
7898
7935
  });
7899
7936
  if (result?.success && result.async !== true && result.removeResult?.removed !== false) {
@@ -7915,6 +7952,7 @@ async function meshRefineBatch(ctx, args = {}) {
7915
7952
  ...args.execute !== void 0 ? { execute: args.execute } : {},
7916
7953
  ...args.dry_run !== void 0 ? { dryRun: args.dry_run } : {},
7917
7954
  ...coordinatorDaemonId ? { coordinatorDaemonId } : {},
7955
+ ...ctx.coordinatorSessionId ? { coordinatorSessionId: ctx.coordinatorSessionId } : {},
7918
7956
  inlineMesh: ctx.mesh
7919
7957
  });
7920
7958
  const payload = unwrapCommandPayload(result) ?? result;