@adhdev/daemon-standalone 1.0.28-rc.2 → 1.0.28-rc.4
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 +11 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/public/assets/{index-B51nIfEq.css → index-8TNNoifN.css} +1 -1
- package/public/assets/{index-CX3wQvni.js → index-QamS-QkE.js} +50 -50
- package/public/index.html +2 -2
- package/vendor/mcp-server/index.js +152 -0
- package/vendor/mcp-server/index.js.map +1 -1
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-
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-QamS-QkE.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/vendor-DyCWA2YZ.js">
|
|
12
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
12
|
+
<link rel="stylesheet" crossorigin href="/assets/index-8TNNoifN.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
15
15
|
<!-- Apply theme immediately to prevent FOIT (Flash of Incorrect Theme) -->
|
|
@@ -393,6 +393,8 @@ var CANONICAL_MESH_TOOL_NAMES = [
|
|
|
393
393
|
"mesh_approve",
|
|
394
394
|
"mesh_answer_question",
|
|
395
395
|
"mesh_list_pending_approvals",
|
|
396
|
+
"mesh_create",
|
|
397
|
+
"mesh_add_node",
|
|
396
398
|
"mesh_clone_node",
|
|
397
399
|
"mesh_remove_node",
|
|
398
400
|
"mesh_refine_node",
|
|
@@ -1116,6 +1118,41 @@ var MESH_LIST_PENDING_APPROVALS_TOOL = {
|
|
|
1116
1118
|
properties: {}
|
|
1117
1119
|
}
|
|
1118
1120
|
};
|
|
1121
|
+
var MESH_CREATE_TOOL = {
|
|
1122
|
+
name: "mesh_create",
|
|
1123
|
+
description: "Bootstrap a brand-new mesh for a Git repository \u2014 the first step for an MCP-only agent that has no mesh yet. Mirrors `adhdev mesh create <name>`. A mesh groups one repo's workspaces/nodes so the coordinator can delegate work across them. You MUST supply the repo identity: pass repo_remote_url (the git remote URL, e.g. git@github.com:user/repo.git or https://github.com/user/repo.git \u2014 the identity is derived from it) OR repo_identity (an explicit normalized identity like github.com/user/repo). At least one is required; there is no auto-detection here (the CLI auto-detects from the current dir, but the MCP server may run elsewhere). Set add_current:true to also register a node in the same call (uses workspace if given, else the daemon's current working directory) \u2014 handy when the daemon runs in the repo you want as the base node. BOOT-GATE / WHEN CALLABLE: this tool is reachable in STANDARD mode (adhdev mcp, no --repo-mesh) \u2014 the bootstrap context where no mesh exists \u2014 and also in mesh mode (where it creates a SEPARATE additional mesh). It is NOT reachable before any mesh exists via mesh mode, because `adhdev mcp --repo-mesh <id>` refuses to start without an existing meshId. So the intended flow is: run standard-mode MCP \u2192 mesh_create \u2192 mesh_add_node \u2192 then relaunch as `adhdev mcp --repo-mesh <returned mesh_id>`. Returns mesh_id (and node_id when add_current is used); use mesh_id for the follow-up mesh_add_node call and to launch mesh mode.",
|
|
1124
|
+
inputSchema: {
|
|
1125
|
+
type: "object",
|
|
1126
|
+
properties: {
|
|
1127
|
+
name: { type: "string", description: 'Human-readable mesh name (e.g. "adhdev-main"). Trimmed, max 100 chars.' },
|
|
1128
|
+
repo_remote_url: { type: "string", description: "Git remote URL of the repo (e.g. git@github.com:user/repo.git). The repo identity is normalized from this. Provide this OR repo_identity." },
|
|
1129
|
+
repo_identity: { type: "string", description: "Explicit normalized repo identity (e.g. github.com/user/repo). Provide this OR repo_remote_url. Wins over repo_remote_url when both are given." },
|
|
1130
|
+
default_branch: { type: "string", description: 'Default branch for the repo (e.g. "main"). Optional; used as the merge/convergence target.' },
|
|
1131
|
+
add_current: { type: "boolean", description: "Also register a node in this same call (parity with CLI --add-current). Uses `workspace` if provided, otherwise the daemon's current working directory." },
|
|
1132
|
+
workspace: { type: "string", description: "Absolute workspace path to register when add_current:true. Ignored unless add_current is true. Defaults to the daemon's cwd." }
|
|
1133
|
+
},
|
|
1134
|
+
required: ["name"]
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
var MESH_ADD_NODE_TOOL = {
|
|
1138
|
+
name: "mesh_add_node",
|
|
1139
|
+
description: "Register a workspace as a node in an EXISTING mesh \u2014 the second bootstrap step after mesh_create (or to add more nodes later). Mirrors `adhdev mesh add-node <mesh_id>` with --workspace / --read-only / --provider-priority. A node is a repo checkout on a daemon that the coordinator can launch agents on and delegate tasks to. mesh_id is REQUIRED in standard mode (pass the id returned by mesh_create); in mesh mode it defaults to the active mesh. workspace is the absolute path to the repo checkout ON THE DAEMON that owns it \u2014 the local base node is added by the daemon that created the mesh. NOTE: this registers an EXISTING directory as a node (including marking one as a worktree via is_worktree). To CREATE a fresh git worktree + branch for isolated parallel work, use mesh_clone_node instead \u2014 that runs the actual `git worktree add`. Returns node_id + workspace so you can immediately target the node with mesh_launch_session / mesh_send_task / mesh_enqueue_task.",
|
|
1140
|
+
inputSchema: {
|
|
1141
|
+
type: "object",
|
|
1142
|
+
properties: {
|
|
1143
|
+
mesh_id: { type: "string", description: "Target mesh id (from mesh_create / mesh_status). Required in standard mode; defaults to the active mesh in mesh mode." },
|
|
1144
|
+
workspace: { type: "string", description: "Absolute path to the repo checkout on the owning daemon (e.g. /Users/me/work/repo). Must be unique within the mesh." },
|
|
1145
|
+
read_only: { type: "boolean", description: "Mark the node read-only (no launches/mutations targeted here). Parity with CLI --read-only." },
|
|
1146
|
+
provider_priority: {
|
|
1147
|
+
type: "array",
|
|
1148
|
+
items: { type: "string" },
|
|
1149
|
+
description: 'Ordered provider types this node prefers when mesh_launch_session omits an explicit type (e.g. ["claude-cli","codex"]). Parity with CLI --provider-priority. A comma-separated string is also accepted.'
|
|
1150
|
+
},
|
|
1151
|
+
is_worktree: { type: "boolean", description: "Mark this workspace as an existing local git worktree (parity with CLI --worktree). This only tags an already-present worktree dir; it does NOT create one \u2014 use mesh_clone_node to create a worktree+branch." }
|
|
1152
|
+
},
|
|
1153
|
+
required: ["workspace"]
|
|
1154
|
+
}
|
|
1155
|
+
};
|
|
1119
1156
|
var MESH_CLONE_NODE_TOOL = {
|
|
1120
1157
|
name: "mesh_clone_node",
|
|
1121
1158
|
description: "Create a new worktree-based node from an existing node for isolated parallel work. Creates a git worktree on a new branch so multiple tasks can run on separate branches simultaneously.",
|
|
@@ -1543,6 +1580,8 @@ var ALL_MESH_TOOLS = [
|
|
|
1543
1580
|
MESH_APPROVE_TOOL,
|
|
1544
1581
|
MESH_ANSWER_QUESTION_TOOL,
|
|
1545
1582
|
MESH_LIST_PENDING_APPROVALS_TOOL,
|
|
1583
|
+
MESH_CREATE_TOOL,
|
|
1584
|
+
MESH_ADD_NODE_TOOL,
|
|
1546
1585
|
MESH_CLONE_NODE_TOOL,
|
|
1547
1586
|
MESH_REMOVE_NODE_TOOL,
|
|
1548
1587
|
MESH_REFINE_NODE_TOOL,
|
|
@@ -7391,6 +7430,100 @@ async function meshRemoveNode(ctx, args) {
|
|
|
7391
7430
|
return JSON.stringify({ ...result || {}, ...transportFallback ? { transportFallback } : {} }, null, 2);
|
|
7392
7431
|
}
|
|
7393
7432
|
|
|
7433
|
+
// src/tools/mesh-tools-crud.ts
|
|
7434
|
+
async function meshCreate(transport, args) {
|
|
7435
|
+
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
7436
|
+
if (!name) {
|
|
7437
|
+
return JSON.stringify({ success: false, error: "name required" }, null, 2);
|
|
7438
|
+
}
|
|
7439
|
+
const repoRemoteUrl = typeof args?.repo_remote_url === "string" ? args.repo_remote_url.trim() : "";
|
|
7440
|
+
const repoIdentity = typeof args?.repo_identity === "string" ? args.repo_identity.trim() : "";
|
|
7441
|
+
const defaultBranch = typeof args?.default_branch === "string" ? args.default_branch.trim() : "";
|
|
7442
|
+
if (!repoRemoteUrl && !repoIdentity) {
|
|
7443
|
+
return JSON.stringify({
|
|
7444
|
+
success: false,
|
|
7445
|
+
error: "Either repo_remote_url or repo_identity is required. Pass the repo's git remote URL (e.g. git@github.com:user/repo.git) or an explicit identity (e.g. github.com/user/repo)."
|
|
7446
|
+
}, null, 2);
|
|
7447
|
+
}
|
|
7448
|
+
const createResult = await transport.command("create_mesh", {
|
|
7449
|
+
name,
|
|
7450
|
+
...repoRemoteUrl ? { repoRemoteUrl } : {},
|
|
7451
|
+
...repoIdentity ? { repoIdentity } : {},
|
|
7452
|
+
...defaultBranch ? { defaultBranch } : {}
|
|
7453
|
+
});
|
|
7454
|
+
const createPayload = unwrapCommandPayload(createResult);
|
|
7455
|
+
const mesh = createPayload?.mesh;
|
|
7456
|
+
if (!createPayload?.success || !mesh?.id) {
|
|
7457
|
+
return JSON.stringify({
|
|
7458
|
+
success: false,
|
|
7459
|
+
error: createPayload?.error || "create_mesh failed",
|
|
7460
|
+
raw: createPayload ?? createResult
|
|
7461
|
+
}, null, 2);
|
|
7462
|
+
}
|
|
7463
|
+
const out = {
|
|
7464
|
+
success: true,
|
|
7465
|
+
mesh_id: mesh.id,
|
|
7466
|
+
name: mesh.name,
|
|
7467
|
+
repo_identity: mesh.repoIdentity,
|
|
7468
|
+
default_branch: mesh.defaultBranch,
|
|
7469
|
+
node_count: Array.isArray(mesh.nodes) ? mesh.nodes.length : 0,
|
|
7470
|
+
next_step: `Add the base node with mesh_add_node (mesh_id: "${mesh.id}", workspace: <repo path>), then start mesh mode with: adhdev mcp --repo-mesh ${mesh.id}`
|
|
7471
|
+
};
|
|
7472
|
+
if (args?.add_current === true) {
|
|
7473
|
+
const workspace = typeof args?.workspace === "string" && args.workspace.trim() ? args.workspace.trim() : "";
|
|
7474
|
+
const addResult = await transport.command("add_mesh_node", {
|
|
7475
|
+
meshId: mesh.id,
|
|
7476
|
+
...workspace ? { workspace } : {},
|
|
7477
|
+
inlineMesh: mesh
|
|
7478
|
+
});
|
|
7479
|
+
const addPayload = unwrapCommandPayload(addResult);
|
|
7480
|
+
if (addPayload?.success && addPayload?.node?.id) {
|
|
7481
|
+
out.node_id = addPayload.node.id;
|
|
7482
|
+
out.node_workspace = addPayload.node.workspace;
|
|
7483
|
+
} else {
|
|
7484
|
+
out.add_current_error = addPayload?.error || "add_mesh_node failed (mesh was still created)";
|
|
7485
|
+
}
|
|
7486
|
+
}
|
|
7487
|
+
return JSON.stringify(out, null, 2);
|
|
7488
|
+
}
|
|
7489
|
+
async function meshAddNode(transport, args, defaultMeshId) {
|
|
7490
|
+
const meshId = typeof args?.mesh_id === "string" && args.mesh_id.trim() ? args.mesh_id.trim() : typeof defaultMeshId === "string" ? defaultMeshId.trim() : "";
|
|
7491
|
+
const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
7492
|
+
if (!meshId) {
|
|
7493
|
+
return JSON.stringify({ success: false, error: "mesh_id required (create one first with mesh_create)." }, null, 2);
|
|
7494
|
+
}
|
|
7495
|
+
if (!workspace) {
|
|
7496
|
+
return JSON.stringify({ success: false, error: "workspace required (absolute path to the repo checkout on the target daemon)." }, null, 2);
|
|
7497
|
+
}
|
|
7498
|
+
const providerPriority = Array.isArray(args?.provider_priority) ? args.provider_priority.map((v) => typeof v === "string" ? v.trim() : "").filter(Boolean) : typeof args?.provider_priority === "string" ? args.provider_priority.split(",").map((v) => v.trim()).filter(Boolean) : [];
|
|
7499
|
+
const addResult = await transport.command("add_mesh_node", {
|
|
7500
|
+
meshId,
|
|
7501
|
+
workspace,
|
|
7502
|
+
...args?.read_only === true ? { readOnly: true } : {},
|
|
7503
|
+
...providerPriority.length ? { providerPriority } : {},
|
|
7504
|
+
...args?.is_worktree === true ? { isLocalWorktree: true } : {},
|
|
7505
|
+
...args?.inline_mesh ? { inlineMesh: args.inline_mesh } : {}
|
|
7506
|
+
});
|
|
7507
|
+
const addPayload = unwrapCommandPayload(addResult);
|
|
7508
|
+
if (!addPayload?.success || !addPayload?.node?.id) {
|
|
7509
|
+
return JSON.stringify({
|
|
7510
|
+
success: false,
|
|
7511
|
+
error: addPayload?.error || "add_mesh_node failed",
|
|
7512
|
+
code: addPayload?.code,
|
|
7513
|
+
raw: addPayload ?? addResult
|
|
7514
|
+
}, null, 2);
|
|
7515
|
+
}
|
|
7516
|
+
return JSON.stringify({
|
|
7517
|
+
success: true,
|
|
7518
|
+
mesh_id: meshId,
|
|
7519
|
+
node_id: addPayload.node.id,
|
|
7520
|
+
workspace: addPayload.node.workspace,
|
|
7521
|
+
read_only: addPayload.node.policy?.readOnly === true,
|
|
7522
|
+
provider_priority: addPayload.node.policy?.providerPriority,
|
|
7523
|
+
next_step: `Node registered. Launch an agent on it with mesh_launch_session (node_id: "${addPayload.node.id}") or delegate work with mesh_send_task / mesh_enqueue_task.`
|
|
7524
|
+
}, null, 2);
|
|
7525
|
+
}
|
|
7526
|
+
|
|
7394
7527
|
// src/tools/mesh-tools-refine.ts
|
|
7395
7528
|
async function meshRefineConfigSchema(ctx) {
|
|
7396
7529
|
const node = resolveRefineConfigNode(ctx);
|
|
@@ -8770,6 +8903,12 @@ async function startMcpServer(opts) {
|
|
|
8770
8903
|
case "mesh_list_pending_approvals":
|
|
8771
8904
|
text = await meshListPendingApprovals(meshCtx, a);
|
|
8772
8905
|
break;
|
|
8906
|
+
case "mesh_create":
|
|
8907
|
+
text = await meshCreate(meshCtx.transport, a);
|
|
8908
|
+
break;
|
|
8909
|
+
case "mesh_add_node":
|
|
8910
|
+
text = await meshAddNode(meshCtx.transport, a, meshCtx.mesh.id);
|
|
8911
|
+
break;
|
|
8773
8912
|
case "mesh_clone_node":
|
|
8774
8913
|
text = await meshCloneNode(meshCtx, a);
|
|
8775
8914
|
break;
|
|
@@ -8907,6 +9046,11 @@ async function startMcpServer(opts) {
|
|
|
8907
9046
|
GIT_DIFF_TOOL,
|
|
8908
9047
|
GIT_CHECKPOINT_TOOL,
|
|
8909
9048
|
GIT_PUSH_TOOL,
|
|
9049
|
+
// Mesh bootstrap: create a mesh + register its first node from an MCP-only agent.
|
|
9050
|
+
// Exposed in standard mode precisely because this is the no-mesh-yet context —
|
|
9051
|
+
// mesh mode refuses to boot without an existing meshId (see the mesh-mode block above).
|
|
9052
|
+
MESH_CREATE_TOOL,
|
|
9053
|
+
MESH_ADD_NODE_TOOL,
|
|
8910
9054
|
...isLocal ? [SCREENSHOT_TOOL] : []
|
|
8911
9055
|
];
|
|
8912
9056
|
const server = new import_server.Server(
|
|
@@ -8996,6 +9140,14 @@ async function startMcpServer(opts) {
|
|
|
8996
9140
|
const text = await checkPending(transport, { format: a.format });
|
|
8997
9141
|
return { content: [{ type: "text", text }] };
|
|
8998
9142
|
}
|
|
9143
|
+
case "mesh_create": {
|
|
9144
|
+
const text = await meshCreate(transport, a);
|
|
9145
|
+
return { content: [{ type: "text", text }] };
|
|
9146
|
+
}
|
|
9147
|
+
case "mesh_add_node": {
|
|
9148
|
+
const text = await meshAddNode(transport, a);
|
|
9149
|
+
return { content: [{ type: "text", text }] };
|
|
9150
|
+
}
|
|
8999
9151
|
default:
|
|
9000
9152
|
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
9001
9153
|
}
|