@debugg-ai/debugg-ai-mcp 1.0.43 → 1.0.45

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.
@@ -9,6 +9,7 @@ import { handleExternalServiceError } from '../utils/errors.js';
9
9
  import { fetchImageAsBase64, imageContentBlock } from '../utils/imageUtils.js';
10
10
  import { DebuggAIServerClient } from '../services/index.js';
11
11
  import { resolveTargetUrl, buildContext, findExistingTunnel, ensureTunnel, sanitizeResponseUrls, touchTunnelById, } from '../utils/tunnelContext.js';
12
+ import { detectRepoName } from '../utils/gitContext.js';
12
13
  import { tunnelManager } from '../services/ngrok/tunnelManager.js';
13
14
  const logger = new Logger({ module: 'testPageChangesHandler' });
14
15
  // Cache the template UUID and project UUIDs within a server session to avoid re-fetching
@@ -80,23 +81,25 @@ export async function testPageChangesHandler(input, context, progressCallback) {
80
81
  logger.info(`Using workflow template: ${template.name} (${template.uuid})`);
81
82
  }
82
83
  // --- Resolve project UUID (best-effort, non-blocking) ---
84
+ // Use explicit repoName if provided, otherwise auto-detect from git remote
85
+ const repoName = input.repoName || detectRepoName();
83
86
  let projectUuid;
84
- if (input.repoName) {
85
- projectUuid = projectUuidCache.get(input.repoName);
87
+ if (repoName) {
88
+ projectUuid = projectUuidCache.get(repoName);
86
89
  if (!projectUuid) {
87
90
  try {
88
- const project = await client.findProjectByRepoName(input.repoName);
91
+ const project = await client.findProjectByRepoName(repoName);
89
92
  if (project) {
90
93
  projectUuid = project.uuid;
91
- projectUuidCache.set(input.repoName, projectUuid);
94
+ projectUuidCache.set(repoName, projectUuid);
92
95
  logger.info(`Resolved project: ${project.name} (${project.uuid})`);
93
96
  }
94
97
  else {
95
- logger.info(`No project found for repo "${input.repoName}" — proceeding without project_id`);
98
+ logger.info(`No project found for repo "${repoName}" — proceeding without project_id`);
96
99
  }
97
100
  }
98
101
  catch (err) {
99
- logger.warn(`Failed to look up project for repo "${input.repoName}": ${err}`);
102
+ logger.warn(`Failed to look up project for repo "${repoName}": ${err}`);
100
103
  }
101
104
  }
102
105
  }
@@ -47,26 +47,30 @@ export class DebuggAIServerClient {
47
47
  this.tunnels = createTunnelsService(this.tx);
48
48
  }
49
49
  /**
50
- * Look up a project by repo name. Uses ?search= then client-side filters
51
- * on repo.name (which is "owner/repo-name" format).
52
- * Returns the first match or null.
50
+ * Look up a project by repo name.
51
+ * Accepts "owner/repo" or bare "repo" — searches with the short name
52
+ * (more likely to match project names) then ranks results by match quality.
53
53
  */
54
54
  async findProjectByRepoName(repoName) {
55
55
  if (!this.tx)
56
56
  throw new Error('Client not initialized — call init() first');
57
- const response = await this.tx.get('api/v1/projects/', { search: repoName });
57
+ // "debugg-ai/react-web-app" short = "react-web-app"
58
+ const short = repoName.includes('/') ? repoName.split('/').pop() : repoName;
59
+ const response = await this.tx.get('api/v1/projects/', { search: short });
58
60
  const projects = response?.results ?? [];
59
61
  if (projects.length === 0)
60
62
  return null;
61
- // Exact match on project name or slug first
62
- const exact = projects.find(p => p.name === repoName || p.slug === repoName);
63
+ // Exact match on full "owner/repo" or short name against project name/slug
64
+ const exact = projects.find(p => p.name === repoName || p.name === short
65
+ || p.slug === repoName || p.slug === short);
63
66
  if (exact)
64
67
  return exact;
65
- // Match on repo.name (owner/repo-name check if it ends with /repoName)
66
- const repoMatch = projects.find(p => p.repo?.name === repoName || p.repo?.name?.endsWith(`/${repoName}`));
68
+ // Match on repo.name — backend may store "owner/repo" or just "repo"
69
+ const repoMatch = projects.find(p => p.repo?.name === repoName || p.repo?.name === short
70
+ || p.repo?.name?.endsWith(`/${short}`));
67
71
  if (repoMatch)
68
72
  return repoMatch;
69
- // Fallback to first result from search
73
+ // Fallback to first search result
70
74
  return projects[0];
71
75
  }
72
76
  /**
@@ -45,7 +45,7 @@ export const testPageChangesTool = {
45
45
  },
46
46
  repoName: {
47
47
  type: "string",
48
- description: "GitHub repository name (e.g. 'my-org/my-repo' or 'my-repo'). Used to link this test to a DebuggAI project for tracking and history."
48
+ description: "GitHub repository name (e.g. 'my-org/my-repo'). Auto-detected from the current git repo only provide this if you want to run against a different project than the one you're in."
49
49
  },
50
50
  },
51
51
  required: ["description", "url"],
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Auto-detect git repo name from the current working directory.
3
+ * Parses the origin remote URL into "owner/repo" format.
4
+ */
5
+ import { execSync } from 'child_process';
6
+ let cached; // undefined = not yet checked
7
+ /**
8
+ * Detect the repo name (e.g. "debugg-ai/debugg-ai-frontend") from git remote origin.
9
+ * Returns null if not inside a git repo or no origin is configured.
10
+ * Result is cached for the process lifetime.
11
+ */
12
+ export function detectRepoName() {
13
+ if (cached !== undefined)
14
+ return cached;
15
+ try {
16
+ const raw = execSync('git remote get-url origin', {
17
+ encoding: 'utf-8',
18
+ timeout: 5000,
19
+ stdio: ['ignore', 'pipe', 'ignore'],
20
+ }).trim();
21
+ cached = parseRepoName(raw);
22
+ }
23
+ catch {
24
+ cached = null;
25
+ }
26
+ return cached;
27
+ }
28
+ /**
29
+ * Parse an origin URL into "owner/repo" format.
30
+ * Handles SSH (git@github.com:owner/repo.git) and HTTPS (https://github.com/owner/repo.git).
31
+ */
32
+ function parseRepoName(remoteUrl) {
33
+ // SSH: git@github.com:owner/repo.git
34
+ const sshMatch = remoteUrl.match(/[:\/]([^/]+\/[^/]+?)(?:\.git)?$/);
35
+ if (sshMatch)
36
+ return sshMatch[1];
37
+ return null;
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@debugg-ai/debugg-ai-mcp",
3
- "version": "1.0.43",
3
+ "version": "1.0.45",
4
4
  "description": "Zero-Config, Fully AI-Managed End-to-End Testing for all code gen platforms.",
5
5
  "type": "module",
6
6
  "bin": {