archbyte 0.4.2 → 0.5.1

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.
Files changed (38) hide show
  1. package/README.md +9 -25
  2. package/bin/archbyte.js +6 -41
  3. package/dist/agents/static/component-detector.js +71 -107
  4. package/dist/agents/static/connection-mapper.js +24 -25
  5. package/dist/agents/static/deep-drill.d.ts +72 -0
  6. package/dist/agents/static/deep-drill.js +388 -0
  7. package/dist/agents/static/doc-parser.js +73 -48
  8. package/dist/agents/static/env-detector.js +3 -6
  9. package/dist/agents/static/event-detector.js +20 -26
  10. package/dist/agents/static/infra-analyzer.js +15 -1
  11. package/dist/agents/static/structure-scanner.js +56 -57
  12. package/dist/agents/static/taxonomy.d.ts +19 -0
  13. package/dist/agents/static/taxonomy.js +147 -0
  14. package/dist/agents/tools/local-fs.js +5 -2
  15. package/dist/cli/analyze.js +49 -27
  16. package/dist/cli/license-gate.js +47 -19
  17. package/dist/cli/run.js +117 -1
  18. package/dist/cli/setup.d.ts +6 -1
  19. package/dist/cli/setup.js +35 -16
  20. package/dist/cli/shared.d.ts +0 -11
  21. package/dist/cli/shared.js +0 -61
  22. package/dist/cli/workflow.js +8 -15
  23. package/dist/server/src/index.js +276 -168
  24. package/package.json +2 -2
  25. package/templates/archbyte.yaml +28 -7
  26. package/ui/dist/assets/index-BQouokNH.css +1 -0
  27. package/ui/dist/assets/index-QllGSFhe.js +72 -0
  28. package/ui/dist/index.html +2 -2
  29. package/dist/cli/arch-diff.d.ts +0 -38
  30. package/dist/cli/arch-diff.js +0 -61
  31. package/dist/cli/diff.d.ts +0 -10
  32. package/dist/cli/diff.js +0 -144
  33. package/dist/cli/patrol.d.ts +0 -18
  34. package/dist/cli/patrol.js +0 -596
  35. package/dist/cli/validate.d.ts +0 -53
  36. package/dist/cli/validate.js +0 -299
  37. package/ui/dist/assets/index-DDCNauh7.css +0 -1
  38. package/ui/dist/assets/index-DO4t5Xu1.js +0 -72
package/README.md CHANGED
@@ -8,40 +8,24 @@ AI-powered architecture visualization for your codebase. Analyzes code, generate
8
8
  # Install
9
9
  curl -fsSL https://archbyte.heartbyte.io/install.sh | bash
10
10
 
11
- # Sign in or create a free account
12
- archbyte login
13
-
14
- # Configure your AI provider (BYOK)
15
- archbyte init
16
-
17
- # Using Claude Code / Codex? Install the MCP server too:
18
- archbyte mcp install
11
+ # Run (auto-configures on first use)
12
+ archbyte run
19
13
  ```
20
14
 
21
- Your API keys stay on your machine. ArchByte never stores or transmits your provider credentials.
15
+ On first run, ArchByte walks you through sign-in and provider setup interactively. Your API keys stay on your machine ArchByte never stores or transmits your provider credentials.
22
16
 
23
- ### Setup with Claude Code
17
+ ### Manual setup
24
18
 
25
- **Option A: MCP** — use ArchByte tools directly in Claude Code. You still need to sign in and configure a provider first:
19
+ Prefer to configure each step separately:
26
20
 
27
21
  ```bash
28
- archbyte mcp install
29
- # or manually:
30
- claude mcp add archbyte --transport stdio -- npx -y archbyte@latest mcp
22
+ archbyte login # Sign in or create a free account
23
+ archbyte init # Configure your AI provider (BYOK)
31
24
  ```
32
25
 
33
- Then just ask Claude Code in plain English:
34
-
35
- ```
36
- "Analyze the architecture of this project"
37
- "Export the architecture as a Mermaid diagram"
38
- "Show me the architecture stats"
39
- "Read the current architecture diagram"
40
- ```
41
-
42
- Available MCP tools: `archbyte_analyze`, `archbyte_generate`, `archbyte_validate` (Pro), `archbyte_export`, `archbyte_stats`, `archbyte_diff`, `archbyte_read_diagram`.
26
+ ### Setup with Claude Code
43
27
 
44
- **Option B: Slash commands** — installed globally so they work in any project:
28
+ Slash commands — installed globally so they work in any project:
45
29
 
46
30
  ```bash
47
31
  mkdir -p ~/.claude/commands
package/bin/archbyte.js CHANGED
@@ -11,10 +11,7 @@ import { Command } from 'commander';
11
11
  import { handleServe } from '../dist/cli/serve.js';
12
12
  import { handleGenerate } from '../dist/cli/generate.js';
13
13
  import { handleStats } from '../dist/cli/stats.js';
14
- import { handleValidate } from '../dist/cli/validate.js';
15
14
  import { handleExport } from '../dist/cli/export.js';
16
- import { handleDiff } from '../dist/cli/diff.js';
17
- import { handlePatrol } from '../dist/cli/patrol.js';
18
15
  import { handleWorkflow } from '../dist/cli/workflow.js';
19
16
  import { handleAnalyze } from '../dist/cli/analyze.js';
20
17
  import { handleConfig } from '../dist/cli/config.js';
@@ -36,9 +33,13 @@ program
36
33
  .version(PKG_VERSION, '-v, --version', 'Show version number')
37
34
  .addHelpText('after', `
38
35
  Quick start:
36
+ $ archbyte run Analyze + open diagram (auto-configures on first run)
37
+
38
+ Or step by step:
39
39
  $ archbyte login Sign in or create a free account
40
40
  $ archbyte init Configure your model provider
41
- $ archbyte run Analyze + open interactive diagram UI
41
+
42
+ Run from your project root, or pass --dir <path> to specify the directory.
42
43
 
43
44
  https://archbyte.heartbyte.io
44
45
  `);
@@ -93,7 +94,7 @@ program
93
94
  .option('--force', 'Force full re-scan (skip incremental detection)')
94
95
  .option('--dry-run', 'Preview without running')
95
96
  .action(async (options) => {
96
- await requireLicense('analyze');
97
+ // handleRun manages login + setup + requireLicense internally
97
98
  await handleRun(options);
98
99
  });
99
100
 
@@ -145,27 +146,6 @@ program
145
146
  await handleStats(options);
146
147
  });
147
148
 
148
- program
149
- .command('validate')
150
- .description('Run architecture fitness function rules')
151
- .option('-d, --diagram <path>', 'Path to architecture JSON (default: .archbyte/architecture.json)')
152
- .option('-c, --config <path>', 'Path to archbyte.yaml config')
153
- .option('--ci', 'Machine-readable JSON output for CI pipelines')
154
- .action(async (options) => {
155
- await requireLicense('analyze');
156
- await handleValidate(options);
157
- });
158
-
159
- program
160
- .command('diff')
161
- .description('Compare architecture snapshots and detect drift')
162
- .requiredOption('-b, --baseline <path>', 'Path to baseline architecture JSON')
163
- .option('-c, --current <path>', 'Path to current architecture JSON (default: .archbyte/architecture.json)')
164
- .option('--config <path>', 'Path to archbyte.yaml config')
165
- .action(async (options) => {
166
- await handleDiff(options);
167
- });
168
-
169
149
  program
170
150
  .command('export')
171
151
  .description('Export architecture to various formats')
@@ -178,21 +158,6 @@ program
178
158
 
179
159
  // — Advanced (Pro) —
180
160
 
181
- program
182
- .command('patrol')
183
- .description('Run continuous architecture health monitoring (Gastown-inspired patrol loop)')
184
- .option('-d, --diagram <path>', 'Path to architecture JSON (default: .archbyte/architecture.json)')
185
- .option('-c, --config <path>', 'Path to archbyte.yaml config')
186
- .option('-i, --interval <duration>', 'Patrol interval: 30s, 5m, 1h (default: 5m)')
187
- .option('--on-violation <action>', 'Action on new violations: log, json (default: log)')
188
- .option('--once', 'Run a single patrol cycle then exit')
189
- .option('-w, --watch', 'Watch source files for changes instead of polling on interval')
190
- .option('--history', 'Show patrol history dashboard')
191
- .action(async (options) => {
192
- await requireLicense('analyze');
193
- await handlePatrol(options);
194
- });
195
-
196
161
  program
197
162
  .command('workflow')
198
163
  .description('Run composable architecture workflows (MEOW-inspired pipeline system)')
@@ -1,75 +1,22 @@
1
1
  // Static Analysis — Component Detector
2
2
  // Detects project components via workspaces, conventional directories, build configs, or single-app fallback
3
3
  import { slugify, assignLayer } from "./utils.js";
4
- // Map well-known deps to architecturally significant tech names
5
- const TECH_MAP = {
6
- react: "React", "react-dom": "React", "next": "Next.js", "vue": "Vue", "nuxt": "Nuxt",
7
- svelte: "Svelte", angular: "Angular", "@angular/core": "Angular",
8
- express: "Express", fastify: "Fastify", "@nestjs/core": "NestJS", hono: "Hono", koa: "Koa",
9
- prisma: "Prisma", "@prisma/client": "Prisma", typeorm: "TypeORM", drizzle: "Drizzle",
10
- sequelize: "Sequelize", mongoose: "Mongoose", pg: "PostgreSQL", mysql2: "MySQL",
11
- redis: "Redis", ioredis: "Redis",
12
- graphql: "GraphQL", "@apollo/server": "Apollo GraphQL",
13
- "socket.io": "Socket.IO", ws: "WebSocket",
14
- tailwindcss: "Tailwind CSS", "@xyflow/react": "React Flow",
15
- commander: "Commander.js", yargs: "Yargs",
16
- vite: "Vite", webpack: "Webpack", esbuild: "esbuild",
17
- typescript: "TypeScript",
18
- kafkajs: "Kafka", amqplib: "RabbitMQ", bullmq: "BullMQ", bull: "Bull",
19
- stripe: "Stripe", "@stripe/stripe-js": "Stripe",
20
- playwright: "Playwright", "@playwright/test": "Playwright",
21
- jest: "Jest", vitest: "Vitest", mocha: "Mocha",
22
- flutter: "Flutter",
23
- };
24
- // Conventional directory → type mapping (hint-based, not exclusive)
25
- const DIR_TYPE_HINTS = {
26
- ui: { type: "frontend", label: "UI" },
27
- web: { type: "frontend", label: "Web App" },
28
- frontend: { type: "frontend", label: "Frontend" },
29
- client: { type: "frontend", label: "Client" },
30
- app: { type: "frontend", label: "App" },
31
- server: { type: "api", label: "Server" },
32
- api: { type: "api", label: "API" },
33
- backend: { type: "api", label: "Backend" },
34
- gateway: { type: "api", label: "Gateway" },
35
- cli: { type: "service", label: "CLI" },
36
- agents: { type: "library", label: "Agents" },
37
- lib: { type: "library", label: "Library" },
38
- packages: { type: "library", label: "Packages" },
39
- shared: { type: "library", label: "Shared" },
40
- common: { type: "library", label: "Common" },
41
- cloud: { type: "service", label: "Cloud" },
42
- infra: { type: "service", label: "Infrastructure" },
43
- deploy: { type: "service", label: "Deployment" },
44
- deployment: { type: "service", label: "Deployment" },
45
- workers: { type: "worker", label: "Workers" },
46
- jobs: { type: "worker", label: "Jobs" },
47
- scripts: { type: "service", label: "Scripts" },
48
- e2e: { type: "service", label: "E2E Tests" },
49
- tests: { type: "service", label: "Tests" },
50
- tools: { type: "service", label: "Tools" },
51
- homepage: { type: "frontend", label: "Homepage" },
52
- docs: { type: "service", label: "Docs" },
53
- };
54
- // Build config files that indicate a directory is a standalone component
55
- const BUILD_CONFIG_FILES = [
56
- "package.json",
57
- "Cargo.toml",
58
- "go.mod",
59
- "pyproject.toml",
60
- "requirements.txt",
61
- "setup.py",
62
- "pubspec.yaml",
63
- "build.gradle",
64
- "pom.xml",
65
- "Gemfile",
66
- "Makefile",
67
- "Dockerfile",
68
- "wrangler.toml",
69
- "tsconfig.json",
70
- ];
4
+ import { categorizeDep, categorizeAllDeps, ROLE_TO_TYPE, MANIFEST_FILES } from "./taxonomy.js";
71
5
  // Skip these dirs — not components
72
6
  import { EXCLUDED_DIRS as SKIP_DIRS } from "./excluded-dirs.js";
7
+ // Structural inference patterns — framework-agnostic grep queries
8
+ const STRUCTURAL_PROBES = [
9
+ // Frontend: renders UI to DOM / uses JSX components
10
+ { grep: "createRoot|ReactDOM|hydrateRoot|createApp.*mount|new Vue|bootstrapApplication", type: "frontend", label: "UI renderer" },
11
+ // API: defines HTTP route handlers
12
+ { grep: "app\\.(get|post|put|delete|use)\\(|router\\.|@(Get|Post|Put|Delete|Controller)|handle.*Request|Hono\\(", type: "api", label: "HTTP routes" },
13
+ // Worker: consumes from queue / processes jobs
14
+ { grep: "\\.process\\(|\\.consume\\(|new Worker\\(|@Processor|celery\\.task", type: "worker", label: "Job processor" },
15
+ // CLI: parses command-line args
16
+ { grep: "\\.command\\(|\\.parse\\(process\\.argv|argparse|@Command\\(", type: "service", label: "CLI" },
17
+ // Server: creates a network listener
18
+ { grep: "createServer\\(|listen\\(\\d|serve\\(|app\\.listen", type: "api", label: "Server" },
19
+ ];
73
20
  export async function detectComponents(tk, structure) {
74
21
  // Strategy 1: Monorepo workspaces
75
22
  if (structure.isMonorepo) {
@@ -157,8 +104,8 @@ async function resolveWorkspacePatterns(tk) {
157
104
  }
158
105
  /**
159
106
  * Scan every top-level directory. If it has a build config, README, Dockerfile,
160
- * or code files, treat it as a component. Use dir name hints + config file analysis
161
- * to determine type.
107
+ * or code files, treat it as a component. Use taxonomy + grep-based structural
108
+ * inference to determine type.
162
109
  */
163
110
  async function detectAllComponents(tk, structure) {
164
111
  const components = [];
@@ -171,7 +118,7 @@ async function detectAllComponents(tk, structure) {
171
118
  continue;
172
119
  const fileNames = entries.map((e) => e.name);
173
120
  // Check for build config files
174
- const hasBuildConfig = BUILD_CONFIG_FILES.some((f) => fileNames.includes(f));
121
+ const hasBuildConfig = MANIFEST_FILES.some((f) => fileNames.includes(f));
175
122
  const hasCode = entries.some((e) => e.type === "file" &&
176
123
  /\.(ts|js|tsx|jsx|py|go|rs|java|rb|dart|kt|swift|c|cpp|cs)$/.test(e.name));
177
124
  const hasSrcDir = entries.some((e) => e.type === "directory" && (e.name === "src" || e.name === "lib" || e.name === "app"));
@@ -181,10 +128,12 @@ async function detectAllComponents(tk, structure) {
181
128
  continue;
182
129
  // Detect language + type + tech stack from config files
183
130
  const detected = await detectFromBuildConfigs(tk, dir, fileNames);
184
- const hint = DIR_TYPE_HINTS[dir.toLowerCase()];
185
- const type = detected.type ?? hint?.type ?? "service";
186
- const label = hint?.label ?? capitalize(dir);
187
- const name = label;
131
+ // If no type from deps, try grep-based structural inference
132
+ if (!detected.type) {
133
+ detected.type = await inferTypeFromCode(tk, dir);
134
+ }
135
+ const type = detected.type ?? "service";
136
+ const name = capitalize(dir);
188
137
  // Read description from sub-README if available
189
138
  let description = detected.description;
190
139
  if (!description && hasReadme) {
@@ -205,6 +154,21 @@ async function detectAllComponents(tk, structure) {
205
154
  }
206
155
  return components;
207
156
  }
157
+ /**
158
+ * Infer component type by grepping actual code in the directory.
159
+ * Runs all probes in parallel — first match with hits wins.
160
+ */
161
+ async function inferTypeFromCode(tk, dir) {
162
+ const results = await Promise.all(STRUCTURAL_PROBES.map(async (probe) => ({
163
+ ...probe,
164
+ hits: await tk.grepFiles(probe.grep, dir),
165
+ })));
166
+ for (const r of results) {
167
+ if (r.hits.length > 0)
168
+ return r.type;
169
+ }
170
+ return null;
171
+ }
208
172
  async function detectFromBuildConfigs(tk, dir, fileNames) {
209
173
  const info = {
210
174
  type: null,
@@ -335,57 +299,57 @@ async function detectFromBuildConfigs(tk, dir, fileNames) {
335
299
  info.technologies = [...new Set(info.technologies)].slice(0, 5);
336
300
  return info;
337
301
  }
338
- function buildSingleAppComponent(structure) {
339
- return {
340
- id: slugify(structure.projectName) ?? "app",
341
- name: structure.projectName || "Application",
342
- type: structure.framework
343
- ? (["React", "Vue", "Svelte", "Angular", "Next.js", "Nuxt"].includes(structure.framework)
344
- ? "frontend"
345
- : "api")
346
- : "service",
347
- layer: "application",
348
- path: ".",
349
- description: "",
350
- technologies: [structure.language, structure.framework].filter(Boolean),
351
- };
352
- }
302
+ /** Detect component type from package.json dependencies using taxonomy */
353
303
  function detectTypeFromDeps(pkg) {
354
304
  const deps = Object.keys({
355
305
  ...pkg.dependencies,
356
306
  ...pkg.devDependencies,
357
307
  });
358
- // Frontend indicators
359
- if (deps.some((d) => ["react", "react-dom", "vue", "svelte", "@angular/core", "next", "nuxt"].includes(d))) {
360
- return "frontend";
361
- }
362
- // API indicators
363
- if (deps.some((d) => ["express", "fastify", "@nestjs/core", "hono", "koa"].includes(d))) {
364
- return "api";
365
- }
366
- // Worker indicators
367
- if (deps.some((d) => ["bullmq", "bull", "bee-queue"].includes(d))) {
368
- return "worker";
369
- }
370
- // Test indicators
371
- if (deps.some((d) => ["@playwright/test", "playwright", "cypress"].includes(d))) {
372
- return "service";
308
+ // Priority: meta-framework > ui-framework > http-framework > queue > test
309
+ const priorityCategories = [
310
+ "meta-framework", "ui-framework", "http-framework", "queue-client", "test-framework",
311
+ ];
312
+ for (const targetCat of priorityCategories) {
313
+ for (const dep of deps) {
314
+ const cat = categorizeDep(dep);
315
+ if (cat?.category === targetCat) {
316
+ return ROLE_TO_TYPE[cat.role] ?? "service";
317
+ }
318
+ }
373
319
  }
374
320
  return "service";
375
321
  }
322
+ /** Extract display-worthy tech stack names from deps using taxonomy */
376
323
  function extractTechStack(pkg) {
377
324
  const deps = Object.keys({
378
325
  ...pkg.dependencies,
379
326
  ...pkg.devDependencies,
380
327
  });
328
+ const categorized = categorizeAllDeps(deps);
329
+ const seen = new Set();
381
330
  const techs = [];
382
- for (const dep of deps) {
383
- if (TECH_MAP[dep] && !techs.includes(TECH_MAP[dep])) {
384
- techs.push(TECH_MAP[dep]);
331
+ for (const cat of categorized.values()) {
332
+ if (!seen.has(cat.displayName)) {
333
+ seen.add(cat.displayName);
334
+ techs.push(cat.displayName);
385
335
  }
386
336
  }
387
337
  return techs.slice(0, 5);
388
338
  }
339
+ function buildSingleAppComponent(structure) {
340
+ const type = structure.framework
341
+ ? (categorizeDep(structure.framework.toLowerCase())?.role === "frontend" ? "frontend" : "api")
342
+ : "service";
343
+ return {
344
+ id: slugify(structure.projectName) ?? "app",
345
+ name: structure.projectName || "Application",
346
+ type,
347
+ layer: "application",
348
+ path: ".",
349
+ description: "",
350
+ technologies: [structure.language, structure.framework].filter(Boolean),
351
+ };
352
+ }
389
353
  function capitalize(s) {
390
354
  return s.charAt(0).toUpperCase() + s.slice(1);
391
355
  }
@@ -2,6 +2,7 @@
2
2
  // Maps connections between components via imports, Docker, K8s, env vars, known SDKs
3
3
  // Only deterministic matches — ambiguous mappings are left as gaps for the LLM
4
4
  import { slugify } from "./utils.js";
5
+ import { categorizeDep } from "./taxonomy.js";
5
6
  export async function mapConnections(tk, components, infra, events, importMap) {
6
7
  const connections = [];
7
8
  const componentIds = new Set(components.map((c) => c.id));
@@ -194,34 +195,32 @@ async function detectServerServesUI(tk, components, connections) {
194
195
  }
195
196
  }
196
197
  async function detectKnownSDKConnections(components, connections) {
197
- const externalTechs = {
198
- Stripe: "stripe-api",
199
- Firebase: "firebase",
200
- Supabase: "supabase",
201
- Redis: "redis",
202
- Kafka: "kafka",
203
- RabbitMQ: "rabbitmq",
204
- "Socket.IO": "websocket",
205
- PostgreSQL: "database",
206
- MySQL: "database",
207
- MongoDB: "database",
198
+ // Role connection type mapping
199
+ const roleToConnType = {
200
+ data: "database",
201
+ messaging: "queue",
202
+ external: "http",
208
203
  };
209
204
  for (const comp of components) {
210
205
  for (const tech of comp.technologies) {
211
- const externalId = externalTechs[tech];
212
- if (externalId) {
213
- const target = components.find((c) => c.id !== comp.id && (c.technologies.includes(tech) ||
214
- c.type === "database" && (externalId === "database")));
215
- if (target) {
216
- connections.push({
217
- from: comp.id,
218
- to: target.id,
219
- type: externalId === "database" ? "database" : "http",
220
- description: `${comp.name} uses ${tech}`,
221
- confidence: 95,
222
- async: false,
223
- });
224
- }
206
+ // Use taxonomy to determine the role/connection type of this tech
207
+ const cat = categorizeDep(tech.toLowerCase());
208
+ if (!cat)
209
+ continue;
210
+ const connType = roleToConnType[cat.role];
211
+ if (!connType)
212
+ continue;
213
+ const target = components.find((c) => c.id !== comp.id && (c.technologies.includes(tech) ||
214
+ (c.type === "database" && connType === "database")));
215
+ if (target) {
216
+ connections.push({
217
+ from: comp.id,
218
+ to: target.id,
219
+ type: connType,
220
+ description: `${comp.name} uses ${tech}`,
221
+ confidence: 95,
222
+ async: false,
223
+ });
225
224
  }
226
225
  }
227
226
  }
@@ -0,0 +1,72 @@
1
+ import type { TreeEntry } from "./types.js";
2
+ export interface DeepDrillResult {
3
+ componentId: string;
4
+ componentName: string;
5
+ componentPath: string;
6
+ scannedAt: string;
7
+ durationMs: number;
8
+ fileTree: TreeEntry[];
9
+ metrics: {
10
+ fileCount: number;
11
+ codeFileCount: number;
12
+ totalLines: number;
13
+ languages: Array<{
14
+ language: string;
15
+ files: number;
16
+ }>;
17
+ };
18
+ structure: {
19
+ entryPoints: string[];
20
+ keyFiles: Array<{
21
+ path: string;
22
+ role: string;
23
+ }>;
24
+ publicExports: string[];
25
+ directories: string[];
26
+ };
27
+ dependencies: {
28
+ manifest: string | null;
29
+ production: Array<{
30
+ name: string;
31
+ category: string | null;
32
+ displayName: string;
33
+ }>;
34
+ development: Array<{
35
+ name: string;
36
+ category: string | null;
37
+ displayName: string;
38
+ }>;
39
+ };
40
+ imports: {
41
+ internalImports: Array<{
42
+ targetPath: string;
43
+ sourceFiles: string[];
44
+ }>;
45
+ externalPackages: string[];
46
+ };
47
+ patterns: Array<{
48
+ type: string;
49
+ label: string;
50
+ matches: Array<{
51
+ file: string;
52
+ line: string;
53
+ content: string;
54
+ }>;
55
+ count: number;
56
+ }>;
57
+ connections: {
58
+ outgoing: Array<{
59
+ targetId: string;
60
+ targetName: string;
61
+ type: string;
62
+ description: string;
63
+ }>;
64
+ incoming: Array<{
65
+ sourceId: string;
66
+ sourceName: string;
67
+ type: string;
68
+ description: string;
69
+ }>;
70
+ };
71
+ }
72
+ export declare function runDeepDrill(projectRoot: string, componentId: string, componentName: string, componentPath: string): Promise<DeepDrillResult>;