@adhdev/daemon-standalone 1.0.48 → 1.0.49-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-Wa0peoIh.js"></script>
10
+ <script type="module" crossorigin src="/assets/index-BeC2kIKA.js"></script>
11
11
  <link rel="modulepreload" crossorigin href="/assets/vendor-DgFmqOGd.js">
12
- <link rel="stylesheet" crossorigin href="/assets/index-CEPCfMWL.css">
12
+ <link rel="stylesheet" crossorigin href="/assets/index-CqyS0XiL.css">
13
13
  </head>
14
14
  <body>
15
15
  <!-- Apply theme immediately to prevent FOIT (Flash of Incorrect Theme) -->
@@ -623,7 +623,9 @@ var CANONICAL_MESH_TOOL_NAMES = [
623
623
  "mesh_magi_kind_panel_list",
624
624
  "mesh_node_slots_set",
625
625
  "mesh_node_slots_list",
626
- "mesh_node_slots_propose"
626
+ "mesh_node_slots_propose",
627
+ "mesh_coordinator_prompt_append_get",
628
+ "mesh_coordinator_prompt_append_set"
627
629
  ];
628
630
  var CANONICAL_MESH_TOOL_COUNT = CANONICAL_MESH_TOOL_NAMES.length;
629
631
  var STATUS_PROBE_ARG_KEY = "_statusProbe";
@@ -1204,12 +1206,13 @@ var MESH_FAST_FORWARD_NODE_TOOL = {
1204
1206
  };
1205
1207
  var MESH_RESTART_DAEMON_TOOL = {
1206
1208
  name: "mesh_restart_daemon",
1207
- description: `Restart a mesh node's daemon, optionally updating it first \u2014 the same path as the dashboard "preview update" button, exposed as a mesh command so a coordinator can roll a worker daemon without a manual restart round-trip. No agent session is launched. mode="upgrade" (default): update to the latest published version on the release channel, then restart; already-latest is a no-op (no restart, returns alreadyLatest:true). mode="restart": pure re-spawn with no reinstall \u2014 restarts even when already latest, with much shorter downtime; use it to reset wedged daemon state (memory leaks, zombie sessions). Idle-gated: a node whose daemon has an active session (generating / waiting_approval / starting) is refused with code "blocking_sessions" so an in-flight turn is never interrupted. self_only=true waives ONLY this mesh's own coordinator session (the structural self-deadlock case \u2014 the coordinator is always generating while it calls). Other sessions still refuse. force=true bypasses the gate entirely: in-flight turns die and the unpersisted pendingOutboundQueue is lost. when_idle=true schedules the restart to run automatically once the daemon goes idle (the safest path \u2014 no queue loss); cancel_when_idle=true cancels it and every response reports the schedule under deferredRestart. kill_session_host=true additionally stops the session-host process, destroying ALL hosted CLI sessions (hard refresh; this is what Windows already does on every upgrade). Default off. Note: on Windows any daemon restart/upgrade terminates all hosted sessions regardless of options; on POSIX hosted sessions survive a plain restart and rebind on next boot. The channel parameter is DEPRECATED and ignored: since Phase 3 the release channel is a build-time identity of the installed binary (stable = adhdev/@latest, preview = adhdev-preview/@next), so an upgrade always targets the daemon's own build track and can never switch channels.`,
1209
+ description: `Restart a mesh node's daemon, optionally updating it first \u2014 the same path as the dashboard "preview update" button, exposed as a mesh command so a coordinator can roll a worker daemon without a manual restart round-trip. No agent session is launched. mode="upgrade" (default): update to the latest published version on the release channel, then restart; already-latest is a no-op (no restart, returns alreadyLatest:true). mode="restart": pure re-spawn with no reinstall \u2014 restarts even when already latest, with much shorter downtime; use it to reset wedged daemon state (memory leaks, zombie sessions). Idle-gated: a node whose daemon has an active session (generating / waiting_approval / starting) is refused with code "blocking_sessions" so an in-flight turn is never interrupted. self_only=true waives ONLY this mesh's own coordinator session (the structural self-deadlock case \u2014 the coordinator is always generating while it calls). Other sessions still refuse. force=true bypasses the gate entirely: in-flight turns die and the unpersisted pendingOutboundQueue is lost. when_idle=true schedules the restart to run automatically once the daemon goes idle (the safest path \u2014 no queue loss); cancel_when_idle=true cancels it and every response reports the schedule under deferredRestart. kill_session_host=true additionally stops the session-host process, destroying ALL hosted CLI sessions (hard refresh; this is what Windows already does on every upgrade). Default off. Note: on Windows any daemon restart/upgrade terminates all hosted sessions regardless of options; on POSIX hosted sessions survive a plain restart and rebind on next boot. Upgrade mode refuses a DOWNGRADE: if the target version resolved from the daemon's build track is OLDER than the running daemon, the call fails with code "downgrade_refused" and reports currentVersion / targetVersion / channel instead of rolling the node back. Pass allow_downgrade=true only for a deliberate rollback. The channel parameter is DEPRECATED and ignored: since Phase 3 the release channel is a build-time identity of the installed binary (stable = adhdev/@latest, preview = adhdev-preview/@next), so an upgrade always targets the daemon's own build track and can never switch channels. When you pass a channel that conflicts with the node's build track, the response now carries a channelOverride object saying so \u2014 the request is not silently honored.`,
1208
1210
  inputSchema: {
1209
1211
  type: "object",
1210
1212
  properties: {
1211
1213
  node_id: { type: "string", description: "Target node ID \u2014 the daemon that owns this node is restarted (and updated, in upgrade mode)." },
1212
- channel: { type: "string", enum: ["stable", "preview"], description: "DEPRECATED and ignored (upgrade mode only). Since Phase 3 the release channel is a build-time identity of the installed binary, so the daemon always upgrades on its own build track. Kept optional so older callers do not break." },
1214
+ channel: { type: "string", enum: ["stable", "preview"], description: "DEPRECATED and ignored (upgrade mode only). Since Phase 3 the release channel is a build-time identity of the installed binary, so the daemon always upgrades on its own build track. Kept optional so older callers do not break. A value conflicting with the node's build track is reported back as channelOverride rather than silently dropped \u2014 it does NOT switch the node's channel." },
1215
+ allow_downgrade: { type: "boolean", description: 'Permit an upgrade whose resolved target is OLDER than the running daemon (upgrade mode only). Default false: such a call is refused with code "downgrade_refused" so a mis-resolved track cannot silently roll a node back. Set true only for a deliberate rollback.' },
1213
1216
  mode: { type: "string", enum: ["upgrade", "restart"], description: "upgrade (default): update to latest on channel, then restart (already-latest is a no-op). restart: pure re-spawn, no reinstall \u2014 restarts even when already latest." },
1214
1217
  force: { type: "boolean", description: "Bypass the idle-gate entirely. Destructive: in-flight turns are killed and the in-memory pendingOutboundQueue is permanently lost. Default false." },
1215
1218
  self_only: { type: "boolean", description: "Waive only this mesh's own coordinator session when it blocks the restart (the coordinator self-deadlock). Other nodes' active sessions still refuse. Default false." },
@@ -1811,6 +1814,27 @@ var MESH_WRITE_MESH_JSON_CONFIG_TOOL = {
1811
1814
  }
1812
1815
  }
1813
1816
  };
1817
+ var MESH_COORDINATOR_PROMPT_APPEND_GET_TOOL = {
1818
+ name: "mesh_coordinator_prompt_append_get",
1819
+ description: "Read the current user-level coordinator prompt APPEND text for a CLI type \u2014 the per-machine file at ~/.adhdev/coordinator-prompts/<cli>.append.md on this MCP server's daemon. Read this before mesh_coordinator_prompt_append_set so you know what you would be replacing. APPEND ONLY: this always stacks AFTER whichever base prompt wins (daemon default, or a mesh-level / user-level override) \u2014 there is no tool to read or write the OVERRIDE (base-replacing) file via MCP; that stays a dashboard-only, human-gated action by design.",
1820
+ inputSchema: {
1821
+ type: "object",
1822
+ properties: {
1823
+ cli_type: { type: "string", description: 'CLI type key, e.g. "claude-cli", "codex-cli". Defaults to "default" (applies to every CLI type without its own file).' }
1824
+ }
1825
+ }
1826
+ };
1827
+ var MESH_COORDINATOR_PROMPT_APPEND_SET_TOOL = {
1828
+ name: "mesh_coordinator_prompt_append_set",
1829
+ description: "Write (or clear) the user-level coordinator prompt APPEND text for a CLI type \u2014 the per-machine file at ~/.adhdev/coordinator-prompts/<cli>.append.md on this MCP server's daemon. Applies to every mesh this daemon coordinates. Empty/omitted content deletes the file (reset to no append). WHOLESALE REPLACE: this replaces the entire append file, not an incremental add \u2014 read the current value first with mesh_coordinator_prompt_append_get if you want to preserve existing text. APPEND ONLY (safety boundary, not a missing feature): this can only ever add text after the base prompt; it can NEVER replace the daemon's base coordinator prompt (the OVERRIDE file), so a coordinator using this tool cannot erase its own core operating rules. There is no override parameter and none will be added.",
1830
+ inputSchema: {
1831
+ type: "object",
1832
+ properties: {
1833
+ cli_type: { type: "string", description: 'CLI type key, e.g. "claude-cli", "codex-cli". Defaults to "default".' },
1834
+ content: { type: "string", description: "The full append text to write. Omit or pass an empty string to clear (delete the file, falling back to no append at this layer)." }
1835
+ }
1836
+ }
1837
+ };
1814
1838
  var ALL_MESH_TOOLS = [
1815
1839
  MESH_STATUS_TOOL,
1816
1840
  MESH_LIST_NODES_TOOL,
@@ -1863,7 +1887,9 @@ var ALL_MESH_TOOLS = [
1863
1887
  MESH_MAGI_KIND_PANEL_LIST_TOOL,
1864
1888
  MESH_NODE_SLOTS_SET_TOOL,
1865
1889
  MESH_NODE_SLOTS_LIST_TOOL,
1866
- MESH_NODE_SLOTS_PROPOSE_TOOL
1890
+ MESH_NODE_SLOTS_PROPOSE_TOOL,
1891
+ MESH_COORDINATOR_PROMPT_APPEND_GET_TOOL,
1892
+ MESH_COORDINATOR_PROMPT_APPEND_SET_TOOL
1867
1893
  ];
1868
1894
 
1869
1895
  // src/tools/mesh-compact.ts
@@ -8132,7 +8158,10 @@ async function meshRestartDaemon(ctx, args) {
8132
8158
  ...args.when_idle === true ? { whenIdle: true } : {},
8133
8159
  ...args.cancel_when_idle === true ? { cancelWhenIdle: true } : {},
8134
8160
  ...typeof args.timeout_ms === "number" ? { timeoutMs: args.timeout_ms } : {},
8135
- ...args.kill_session_host === true ? { killSessionHost: true } : {}
8161
+ ...args.kill_session_host === true ? { killSessionHost: true } : {},
8162
+ // Forwarded only when explicitly set, so the default stays "refuse
8163
+ // a downgrade" for every caller that does not opt in.
8164
+ ...args.allow_downgrade === true ? { allowDowngrade: true } : {}
8136
8165
  });
8137
8166
  return JSON.stringify(unwrapCommandPayload(result), null, 2);
8138
8167
  } catch (e) {
@@ -8443,6 +8472,41 @@ async function meshAddNode(transport, args, defaultMeshId) {
8443
8472
  }, null, 2);
8444
8473
  }
8445
8474
 
8475
+ // src/tools/mesh-tools-coordinator-prompt.ts
8476
+ var DEFAULT_CLI_TYPE_KEY = "default";
8477
+ async function meshCoordinatorPromptAppendGet(ctx, args = {}) {
8478
+ const key = readString(args.cli_type) || DEFAULT_CLI_TYPE_KEY;
8479
+ const result = unwrapCommandPayload(await ctx.transport.command("list_coordinator_prompts", {}));
8480
+ if (!result?.success) {
8481
+ return JSON.stringify({ success: false, error: result?.error || "list_coordinator_prompts failed" }, null, 2);
8482
+ }
8483
+ const entry = result.entries?.[key];
8484
+ return JSON.stringify({
8485
+ success: true,
8486
+ cli_type: key,
8487
+ append: entry?.append || "",
8488
+ dir: result.dir
8489
+ }, null, 2);
8490
+ }
8491
+ async function meshCoordinatorPromptAppendSet(ctx, args) {
8492
+ const key = readString(args.cli_type) || DEFAULT_CLI_TYPE_KEY;
8493
+ const content = typeof args.content === "string" ? args.content : "";
8494
+ const result = unwrapCommandPayload(await ctx.transport.command("write_coordinator_prompt", {
8495
+ key,
8496
+ kind: "append",
8497
+ content
8498
+ }));
8499
+ if (!result?.success) {
8500
+ return JSON.stringify({ success: false, error: result?.error || "write_coordinator_prompt failed" }, null, 2);
8501
+ }
8502
+ return JSON.stringify({
8503
+ success: true,
8504
+ cli_type: key,
8505
+ cleared: !content.trim(),
8506
+ path: result.path
8507
+ }, null, 2);
8508
+ }
8509
+
8446
8510
  // src/tools/mesh-tools-refine.ts
8447
8511
  async function meshRefineConfigSchema(ctx) {
8448
8512
  const node = resolveRefineConfigNode(ctx);
@@ -9985,6 +10049,12 @@ async function startMcpServer(opts) {
9985
10049
  case "mesh_node_slots_propose":
9986
10050
  text = await meshNodeSlotsPropose(meshCtx, a);
9987
10051
  break;
10052
+ case "mesh_coordinator_prompt_append_get":
10053
+ text = await meshCoordinatorPromptAppendGet(meshCtx, a);
10054
+ break;
10055
+ case "mesh_coordinator_prompt_append_set":
10056
+ text = await meshCoordinatorPromptAppendSet(meshCtx, a);
10057
+ break;
9988
10058
  default:
9989
10059
  return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
9990
10060
  }