@mgsoftwarebv/mg-dashboard-mcp 7.0.16 → 7.0.18

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
@@ -6204,55 +6204,45 @@ function normalizeRepoIdentifier(value) {
6204
6204
  }
6205
6205
  return s || null;
6206
6206
  }
6207
+ var HANDOFF_PROMPT_CHARS = 4e3;
6207
6208
  async function queueAgentRun(args2) {
6208
6209
  const db2 = getDb();
6209
- const gitMode = args2.gitMode ?? "worktree";
6210
6210
  const model = args2.model ?? null;
6211
- const metadata = args2.metadata ?? {};
6211
+ const handoffPrompt = args2.prompt.trim().slice(0, HANDOFF_PROMPT_CHARS);
6212
+ const metadata = { ...args2.metadata ?? {}, source: args2.source };
6213
+ await db2.execute(sql`
6214
+ INSERT INTO agent_host_command (host_id, user_id, command_type, payload)
6215
+ VALUES (
6216
+ ${args2.workspace.host_id}, ${args2.userId}, 'open_chat_in_ide',
6217
+ ${JSON.stringify({
6218
+ workspacePath: args2.workspace.path,
6219
+ prompt: handoffPrompt,
6220
+ model
6221
+ })}::jsonb
6222
+ )
6223
+ `);
6212
6224
  const conversationRows = await db2.execute(sql`
6213
6225
  INSERT INTO agent_conversation (
6214
- user_id, host_id, workspace_id, runtime, source, title, status, model, metadata
6226
+ user_id, host_id, workspace_id, runtime, source,
6227
+ local_conversation_id, title, status, model, last_message_at, metadata
6215
6228
  ) VALUES (
6216
- ${args2.userId}, ${args2.workspace.host_id}, ${args2.workspace.id},
6217
- 'local', ${args2.source}, ${args2.title}, 'running', ${model},
6229
+ ${args2.userId}, ${args2.workspace.host_id}, ${args2.workspace.id}, 'ide',
6230
+ 'ide_import', NULL, ${args2.title}, 'idle', ${model}, now(),
6218
6231
  ${JSON.stringify(metadata)}::jsonb
6219
6232
  )
6220
6233
  RETURNING id
6221
6234
  `);
6222
6235
  const conversationId = conversationRows[0]?.id;
6223
6236
  if (!conversationId) return null;
6224
- const runRows = await db2.execute(sql`
6225
- INSERT INTO agent_run (
6226
- conversation_id, workspace_id, host_id, user_id, runtime, status,
6227
- prompt, model, git_mode, source
6228
- ) VALUES (
6229
- ${conversationId}, ${args2.workspace.id}, ${args2.workspace.host_id},
6230
- ${args2.userId}, 'local', 'queued', ${args2.prompt}, ${model}, ${gitMode},
6231
- ${args2.source}
6232
- )
6233
- RETURNING id
6234
- `);
6235
- const runId = runRows[0]?.id;
6236
- if (!runId) return null;
6237
- const payload = {
6238
- runId,
6239
- conversationId,
6240
- workspacePath: args2.workspace.path,
6241
- prompt: args2.prompt,
6242
- model,
6243
- gitMode,
6244
- sdkAgentId: null,
6245
- contextReplay: null,
6246
- ...metadata
6247
- };
6248
6237
  await db2.execute(sql`
6249
- INSERT INTO agent_host_command (host_id, user_id, run_id, command_type, payload)
6250
- VALUES (
6251
- ${args2.workspace.host_id}, ${args2.userId}, ${runId}, 'start_run',
6252
- ${JSON.stringify(payload)}::jsonb
6238
+ INSERT INTO agent_message (
6239
+ conversation_id, user_id, role, content, blocks, is_streaming, local_created_at
6240
+ ) VALUES (
6241
+ ${conversationId}, ${args2.userId}, 'user', ${handoffPrompt},
6242
+ '[]'::jsonb, false, now()
6253
6243
  )
6254
6244
  `);
6255
- return { conversationId, runId };
6245
+ return { conversationId };
6256
6246
  }
6257
6247
  function toTarget(row) {
6258
6248
  return {
@@ -6286,7 +6276,9 @@ async function listRemoteWorkspaces() {
6286
6276
  w.default_git_mode, w.last_synced_at
6287
6277
  FROM agent_workspace w
6288
6278
  INNER JOIN agent_host h ON h.id = w.host_id
6289
- LEFT JOIN "user" u ON u.id = w.user_id
6279
+ -- "user".id is uuid, agent_workspace.user_id is text (Better Auth ids):
6280
+ -- cast the uuid side so the join doesn't fail with "uuid = text".
6281
+ LEFT JOIN "user" u ON u.id::text = w.user_id
6290
6282
  WHERE w.status = 'active' AND h.revoked_at IS NULL
6291
6283
  ORDER BY host_online DESC, w.last_synced_at DESC NULLS LAST
6292
6284
  `);
@@ -6297,7 +6289,8 @@ function matchesWho(target, who) {
6297
6289
  if (!needle) return true;
6298
6290
  const name = (target.ownerName ?? "").toLowerCase();
6299
6291
  const email = (target.ownerEmail ?? "").toLowerCase();
6300
- return name.includes(needle) || email.includes(needle);
6292
+ const host = target.hostName.toLowerCase();
6293
+ return name.includes(needle) || email.includes(needle) || host.includes(needle);
6301
6294
  }
6302
6295
  function matchesProject(target, project) {
6303
6296
  const repoTarget = normalizeRepoIdentifier(project);
@@ -10353,7 +10346,7 @@ var TOOLS = [
10353
10346
  // ----- Cursor Remote (Agent Control) -----
10354
10347
  {
10355
10348
  name: "cursor-remote-list",
10356
- description: "List the paired developer machines (agent hosts) and their workspaces that a headless Cursor agent run can be started on, across the whole team. Each workspace shows its owner, git repository + branch, online status and default git mode. Call this FIRST to discover valid `who` (owner) and `project` (repo/workspace) values before calling cursor-remote-run. Only online hosts can run.",
10349
+ description: "List the paired developer machines (agent hosts) and their workspaces that a Cursor agent chat can be opened on, across the whole team. Each workspace shows its owner, git repository + branch and online status. Call this FIRST to discover valid `who` (owner) and `project` (repo/workspace) values before calling cursor-remote-run. Only online hosts can be targeted.",
10357
10350
  inputSchema: {
10358
10351
  type: "object",
10359
10352
  properties: {
@@ -10366,13 +10359,13 @@ var TOOLS = [
10366
10359
  },
10367
10360
  {
10368
10361
  name: "cursor-remote-run",
10369
- description: "Start a headless Cursor agent run on a teammate's machine to make a code change. Resolve `who` (workspace owner name/email) + `project` (repo 'org/repo', URL, or workspace name) to a single online workspace, then queue the run via the agent-host daemon (@cursor/sdk). Use this when an AI (e.g. a ticket assistant) should hand a self-contained, well-scoped fix prompt to a developer's PC. Default git mode is 'worktree': the change runs in an isolated worktree and ends in a DIFF APPROVAL the owner reviews on the dashboard/mobile \u2014 nothing lands on their branch automatically. Returns the conversationId + runId and a dashboard link to follow progress. Call cursor-remote-list first if unsure about who/project.",
10362
+ description: "Open a Cursor agent chat in a teammate's real IDE to make a code change. Resolve `who` (workspace owner name/email or machine name) + `project` (repo 'org/repo', URL, or workspace name) to a single online workspace, then hand off via the agent-host daemon: it opens that workspace's Cursor window, prefills the prompt and auto-submits it, so the developer sees the agent working live in their IDE. Use this when an AI (e.g. a ticket assistant) should hand a self-contained, well-scoped fix prompt to a developer's PC. There is no headless run and no diff-approval step \u2014 the developer reviews and commits in the IDE itself. Returns the conversationId and a dashboard link to follow the chat. Call cursor-remote-list first if unsure about who/project.",
10370
10363
  inputSchema: {
10371
10364
  type: "object",
10372
10365
  properties: {
10373
10366
  who: {
10374
10367
  type: "string",
10375
- description: "Workspace owner to target, matched case-insensitively against full name or email (e.g. 'Sidney'). Optional, but recommended when several people have the same repo paired."
10368
+ description: "Who/where to target, matched case-insensitively against the workspace owner (full name or email) AND the host/machine name (e.g. 'Jordan' matches the 'Jordan Laptop' host). Paired machines often share one account, so the machine name is usually the distinguishing factor. Optional, but recommended when several machines have the same repo paired."
10376
10369
  },
10377
10370
  project: {
10378
10371
  type: "string",
@@ -10386,11 +10379,6 @@ var TOOLS = [
10386
10379
  type: "string",
10387
10380
  description: "Optional Cursor model slug to run with (e.g. a Sonnet-tier model). Omit to use the host default."
10388
10381
  },
10389
- gitMode: {
10390
- type: "string",
10391
- enum: ["worktree", "in_place"],
10392
- description: "'worktree' (default, recommended): isolated worktree + diff approval. 'in_place': applies directly in the working tree (no isolation) \u2014 use only when explicitly desired."
10393
- },
10394
10382
  branch: {
10395
10383
  type: "string",
10396
10384
  description: "Optional: prefer a workspace already checked out on this branch when several match."
@@ -10657,7 +10645,6 @@ ${facets.join(", ")}` : ""),
10657
10645
  project: w.name,
10658
10646
  repo: w.gitRepository,
10659
10647
  branch: w.gitBranch,
10660
- defaultGitMode: w.defaultGitMode,
10661
10648
  path: w.path,
10662
10649
  lastSyncedAt: w.lastSyncedAt
10663
10650
  }));
@@ -10691,7 +10678,6 @@ ${facets.join(", ")}` : ""),
10691
10678
  const who = typeof a.who === "string" ? a.who.trim() : null;
10692
10679
  const branch = typeof a.branch === "string" ? a.branch.trim() : null;
10693
10680
  const model = typeof a.model === "string" ? a.model.trim() : null;
10694
- const gitMode = a.gitMode === "in_place" ? "in_place" : "worktree";
10695
10681
  const resolution = await resolveRemoteTarget({ who, project, branch });
10696
10682
  if (!resolution.ok) {
10697
10683
  const describe = (c) => ` - ${c.ownerName ?? c.ownerEmail ?? c.ownerUserId} \xB7 ${c.name}${c.gitRepository ? ` (${c.gitRepository}${c.gitBranch ? `@${c.gitBranch}` : ""})` : ""}`;
@@ -10722,7 +10708,6 @@ ${candidates || " (none online \u2014 start the MG Agent Host)"}`
10722
10708
  title,
10723
10709
  source: "mcp_remote",
10724
10710
  model,
10725
- gitMode,
10726
10711
  metadata: {
10727
10712
  requestedBy: ctx.userId,
10728
10713
  who: who ?? null,
@@ -10731,7 +10716,7 @@ ${candidates || " (none online \u2014 start the MG Agent Host)"}`
10731
10716
  });
10732
10717
  if (!queued) {
10733
10718
  return {
10734
- content: [{ type: "text", text: "Error: failed to queue the agent run" }]
10719
+ content: [{ type: "text", text: "Error: failed to open the IDE chat" }]
10735
10720
  };
10736
10721
  }
10737
10722
  const conversationUrl = `${dashboardBaseUrl}/cursor-remote?conversation=${queued.conversationId}`;
@@ -10741,17 +10726,15 @@ ${candidates || " (none online \u2014 start the MG Agent Host)"}`
10741
10726
  type: "text",
10742
10727
  text: JSON.stringify(
10743
10728
  {
10744
- status: "queued",
10729
+ status: "opened",
10745
10730
  owner: target.ownerName ?? target.ownerEmail ?? target.ownerUserId,
10746
10731
  host: target.hostName,
10747
10732
  project: target.name,
10748
10733
  repo: target.gitRepository,
10749
10734
  branch: target.gitBranch,
10750
- gitMode,
10751
10735
  conversationId: queued.conversationId,
10752
- runId: queued.runId,
10753
10736
  conversationUrl,
10754
- note: gitMode === "worktree" ? "Runs in an isolated worktree and ends in a diff approval the owner reviews \u2014 nothing lands on their branch automatically." : "Runs in_place in the working tree (no isolation)."
10737
+ note: "Opens the workspace's real Cursor IDE, prefills the prompt and auto-submits it. The developer sees the agent working live and reviews/commits in the IDE \u2014 no diff approval step."
10755
10738
  },
10756
10739
  null,
10757
10740
  2