@dependabit/detector 0.1.15 → 0.1.17

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 (39) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/detector.d.ts +179 -12
  3. package/dist/detector.d.ts.map +1 -1
  4. package/dist/detector.js +121 -12
  5. package/dist/detector.js.map +1 -1
  6. package/dist/diff-parser.js.map +1 -1
  7. package/dist/llm/client.d.ts +111 -2
  8. package/dist/llm/client.d.ts.map +1 -1
  9. package/dist/llm/client.js +33 -1
  10. package/dist/llm/client.js.map +1 -1
  11. package/dist/llm/copilot.d.ts.map +1 -1
  12. package/dist/llm/copilot.js +1 -7
  13. package/dist/llm/copilot.js.map +1 -1
  14. package/dist/llm/prompts.d.ts +42 -2
  15. package/dist/llm/prompts.d.ts.map +1 -1
  16. package/dist/llm/prompts.js +42 -2
  17. package/dist/llm/prompts.js.map +1 -1
  18. package/dist/parsers/code-comments.js.map +1 -1
  19. package/dist/parsers/package-files.js.map +1 -1
  20. package/dist/parsers/readme.js.map +1 -1
  21. package/package.json +26 -9
  22. package/src/detector.ts +0 -1043
  23. package/src/diff-parser.ts +0 -257
  24. package/src/index.ts +0 -43
  25. package/src/llm/client.ts +0 -85
  26. package/src/llm/copilot.ts +0 -150
  27. package/src/llm/prompts.ts +0 -111
  28. package/src/parsers/code-comments.ts +0 -178
  29. package/src/parsers/package-files.ts +0 -156
  30. package/src/parsers/readme.ts +0 -191
  31. package/test/detector.test.ts +0 -169
  32. package/test/diff-parser.test.ts +0 -187
  33. package/test/llm/client.test.ts +0 -31
  34. package/test/llm/copilot.test.ts +0 -334
  35. package/test/parsers/code-comments.test.ts +0 -98
  36. package/test/parsers/package-files.test.ts +0 -52
  37. package/test/parsers/readme.test.ts +0 -52
  38. package/tsconfig.json +0 -10
  39. package/tsconfig.tsbuildinfo +0 -1
@@ -1,257 +0,0 @@
1
- /**
2
- * Diff Parser
3
- * Parse git diffs to extract meaningful changes for dependency analysis
4
- */
5
-
6
- import type { CommitFile } from '@dependabit/github-client';
7
-
8
- export interface DiffParseResult {
9
- additions: string[];
10
- deletions: string[];
11
- }
12
-
13
- export interface ExtractedContent {
14
- urls: string[];
15
- packageDeps: string[];
16
- }
17
-
18
- export interface ChangedFilesResult {
19
- relevantFiles: string[];
20
- packageFiles: string[];
21
- documentationFiles: string[];
22
- }
23
-
24
- // URL pattern to match HTTP(S) URLs
25
- const URL_PATTERN = /https?:\/\/[^\s<>"{}|\\^`[\]]+/gi;
26
-
27
- // Package dependency patterns
28
- const PACKAGE_DEP_PATTERNS = {
29
- packageJson: /"([^"]+)":\s*"[\^~]?[\d.]+"/g,
30
- requirementsTxt: /^([a-zA-Z0-9_-]+)[>=<~!]=.*/gm,
31
- cargoToml:
32
- /^(?!\s*(?:name|version|authors|edition|description|license|workspace|build|default-run|repository|homepage|documentation|readme|keywords|categories|exclude|include|publish|resolver)\s*=)\s*([a-zA-Z0-9_-]+)\s*=.*/gm
33
- };
34
-
35
- // File extensions relevant for dependency analysis
36
- const RELEVANT_EXTENSIONS = [
37
- '.md',
38
- '.txt',
39
- '.rst',
40
- '.adoc', // Documentation
41
- '.ts',
42
- '.js',
43
- '.py',
44
- '.rs',
45
- '.go',
46
- '.java',
47
- '.cpp',
48
- '.c',
49
- '.h', // Code
50
- '.json',
51
- '.toml',
52
- '.yaml',
53
- '.yml', // Config
54
- '.html',
55
- '.xml' // Markup
56
- ];
57
-
58
- // Package manifest files
59
- const PACKAGE_MANIFEST_FILES = [
60
- 'package.json',
61
- 'requirements.txt',
62
- 'Cargo.toml',
63
- 'go.mod',
64
- 'pom.xml',
65
- 'build.gradle',
66
- 'Gemfile',
67
- 'composer.json'
68
- ];
69
-
70
- /**
71
- * Parse a unified diff and extract additions and deletions
72
- */
73
- export function parseDiff(patch: string): DiffParseResult {
74
- const additions: string[] = [];
75
- const deletions: string[] = [];
76
-
77
- if (!patch) {
78
- return { additions, deletions };
79
- }
80
-
81
- const lines = patch.split('\n');
82
-
83
- for (const line of lines) {
84
- if (line.startsWith('+') && !line.startsWith('+++')) {
85
- // Addition (remove the + prefix)
86
- additions.push(line.substring(1));
87
- } else if (line.startsWith('-') && !line.startsWith('---')) {
88
- // Deletion (remove the - prefix)
89
- deletions.push(line.substring(1));
90
- }
91
- // Ignore context lines (no prefix or space prefix)
92
- }
93
-
94
- return { additions, deletions };
95
- }
96
-
97
- /**
98
- * Extract meaningful content from added lines
99
- */
100
- export function extractAddedContent(additions: string[], filename?: string): ExtractedContent {
101
- const urls: string[] = [];
102
- const packageDeps: string[] = [];
103
-
104
- const content = additions.join('\n');
105
-
106
- // Extract URLs
107
- const urlMatches = content.matchAll(URL_PATTERN);
108
- for (const match of urlMatches) {
109
- urls.push(match[0]);
110
- }
111
-
112
- // Extract package dependencies based on file type
113
- if (filename) {
114
- const lowerFilename = filename.toLowerCase();
115
- if (lowerFilename === 'package.json') {
116
- const depMatches = content.matchAll(PACKAGE_DEP_PATTERNS.packageJson);
117
- for (const match of depMatches) {
118
- if (match[1]) packageDeps.push(match[1]);
119
- }
120
- } else if (lowerFilename === 'requirements.txt') {
121
- const depMatches = content.matchAll(PACKAGE_DEP_PATTERNS.requirementsTxt);
122
- for (const match of depMatches) {
123
- if (match[1]) packageDeps.push(match[1]);
124
- }
125
- } else if (lowerFilename === 'cargo.toml') {
126
- const depMatches = content.matchAll(PACKAGE_DEP_PATTERNS.cargoToml);
127
- for (const match of depMatches) {
128
- if (match[1]) packageDeps.push(match[1]);
129
- }
130
- }
131
- }
132
-
133
- return {
134
- urls: Array.from(new Set(urls)),
135
- packageDeps: Array.from(new Set(packageDeps))
136
- };
137
- }
138
-
139
- /**
140
- * Extract meaningful content from removed lines
141
- */
142
- export function extractRemovedContent(deletions: string[], filename?: string): ExtractedContent {
143
- // Use the same logic as extractAddedContent
144
- return extractAddedContent(deletions, filename);
145
- }
146
-
147
- /**
148
- * Identify files relevant for dependency analysis
149
- *
150
- * Note: Filenames in relevantFiles preserve their original case from the commit.
151
- * Case-insensitive matching is used for identification, but original casing is maintained
152
- * for consistency with file system operations.
153
- */
154
- export function getChangedFiles(files: CommitFile[]): ChangedFilesResult {
155
- const relevantFiles: string[] = [];
156
- const packageFiles: string[] = [];
157
- const documentationFiles: string[] = [];
158
-
159
- for (const file of files) {
160
- const filename = file.filename.toLowerCase();
161
- const basename = filename.split('/').pop() || '';
162
-
163
- // Check if it's a package manifest file (case-insensitive comparison)
164
- const isPackageFile = PACKAGE_MANIFEST_FILES.some(
165
- (manifestFile) => manifestFile.toLowerCase() === basename
166
- );
167
-
168
- if (isPackageFile) {
169
- packageFiles.push(file.filename);
170
- relevantFiles.push(file.filename);
171
- continue;
172
- }
173
-
174
- // Check if it's a documentation file
175
- if (
176
- basename.startsWith('readme') ||
177
- filename.includes('/docs/') ||
178
- filename.includes('/documentation/')
179
- ) {
180
- documentationFiles.push(file.filename);
181
- relevantFiles.push(file.filename);
182
- continue;
183
- }
184
-
185
- // Check if it has a relevant extension
186
- const hasRelevantExtension = RELEVANT_EXTENSIONS.some((ext) => filename.endsWith(ext));
187
-
188
- if (hasRelevantExtension) {
189
- relevantFiles.push(file.filename);
190
- }
191
- }
192
-
193
- return {
194
- relevantFiles: Array.from(new Set(relevantFiles)),
195
- packageFiles: Array.from(new Set(packageFiles)),
196
- documentationFiles: Array.from(new Set(documentationFiles))
197
- };
198
- }
199
-
200
- /**
201
- * Parse all diffs from commit files
202
- */
203
- export function parseCommitDiffs(files: CommitFile[]): Map<string, DiffParseResult> {
204
- const diffMap = new Map<string, DiffParseResult>();
205
-
206
- for (const file of files) {
207
- if (file.patch) {
208
- diffMap.set(file.filename, parseDiff(file.patch));
209
- }
210
- }
211
-
212
- return diffMap;
213
- }
214
-
215
- /**
216
- * Extract all dependency-related content from commit diffs
217
- */
218
- export function extractDependencyChanges(files: CommitFile[]): {
219
- addedUrls: string[];
220
- removedUrls: string[];
221
- addedPackages: string[];
222
- removedPackages: string[];
223
- changedFiles: ChangedFilesResult;
224
- } {
225
- const changedFiles = getChangedFiles(files);
226
- const allAddedUrls: string[] = [];
227
- const allRemovedUrls: string[] = [];
228
- const allAddedPackages: string[] = [];
229
- const allRemovedPackages: string[] = [];
230
-
231
- for (const file of files) {
232
- if (!file.patch || !changedFiles.relevantFiles.includes(file.filename)) {
233
- continue;
234
- }
235
-
236
- const diff = parseDiff(file.patch);
237
- const basename = file.filename.split('/').pop();
238
-
239
- // Extract added content
240
- const addedContent = extractAddedContent(diff.additions, basename);
241
- allAddedUrls.push(...addedContent.urls);
242
- allAddedPackages.push(...addedContent.packageDeps);
243
-
244
- // Extract removed content
245
- const removedContent = extractRemovedContent(diff.deletions, basename);
246
- allRemovedUrls.push(...removedContent.urls);
247
- allRemovedPackages.push(...removedContent.packageDeps);
248
- }
249
-
250
- return {
251
- addedUrls: Array.from(new Set(allAddedUrls)),
252
- removedUrls: Array.from(new Set(allRemovedUrls)),
253
- addedPackages: Array.from(new Set(allAddedPackages)),
254
- removedPackages: Array.from(new Set(allRemovedPackages)),
255
- changedFiles
256
- };
257
- }
package/src/index.ts DELETED
@@ -1,43 +0,0 @@
1
- // Entry point for @dependabit/detector
2
-
3
- // LLM Provider
4
- export type {
5
- LLMProvider,
6
- LLMProviderConfig,
7
- LLMResponse,
8
- RateLimitInfo,
9
- DetectedDependency,
10
- LLMUsageMetadata
11
- } from './llm/client.js';
12
- export { GitHubCopilotProvider } from './llm/copilot.js';
13
- export { SYSTEM_PROMPT, createDetectionPrompt, createClassificationPrompt } from './llm/prompts.js';
14
-
15
- // Parsers
16
- export type { ExtractedReference } from './parsers/readme.js';
17
- export { parseReadme, extractGitHubReferences } from './parsers/readme.js';
18
-
19
- export type { CommentReference } from './parsers/code-comments.js';
20
- export { parseCodeComments, extractSpecReferences } from './parsers/code-comments.js';
21
-
22
- export type { PackageMetadata } from './parsers/package-files.js';
23
- export {
24
- parsePackageJson,
25
- parseRequirementsTxt,
26
- parseCargoToml,
27
- parseGoMod
28
- } from './parsers/package-files.js';
29
-
30
- // Diff Parser
31
- export type { DiffParseResult, ExtractedContent, ChangedFilesResult } from './diff-parser.js';
32
- export {
33
- parseDiff,
34
- extractAddedContent,
35
- extractRemovedContent,
36
- getChangedFiles,
37
- parseCommitDiffs,
38
- extractDependencyChanges
39
- } from './diff-parser.js';
40
-
41
- // Detector
42
- export type { DetectorOptions, DetectionResult } from './detector.js';
43
- export { Detector } from './detector.js';
package/src/llm/client.ts DELETED
@@ -1,85 +0,0 @@
1
- /**
2
- * LLM Provider Interface
3
- * Abstraction layer for different LLM providers (GitHub Copilot, Claude, OpenAI, etc.)
4
- */
5
-
6
- import type { z } from 'zod';
7
-
8
- export interface RateLimitInfo {
9
- remaining: number;
10
- limit: number;
11
- resetAt: Date;
12
- }
13
-
14
- export interface LLMUsageMetadata {
15
- promptTokens: number;
16
- completionTokens: number;
17
- totalTokens: number;
18
- model: string;
19
- latencyMs: number;
20
- }
21
-
22
- export interface DetectedDependency {
23
- url: string;
24
- name: string;
25
- description?: string;
26
- type:
27
- | 'reference-implementation'
28
- | 'schema'
29
- | 'documentation'
30
- | 'research-paper'
31
- | 'api-example'
32
- | 'other';
33
- confidence: number; // 0.0 - 1.0
34
- reasoning?: string; // Why this was detected as a dependency
35
- }
36
-
37
- export interface LLMResponse {
38
- dependencies: DetectedDependency[];
39
- usage: LLMUsageMetadata;
40
- rawResponse?: string; // For debugging
41
- }
42
-
43
- export interface LLMProviderConfig {
44
- apiKey?: string;
45
- endpoint?: string;
46
- model?: string;
47
- maxTokens?: number;
48
- temperature?: number;
49
- }
50
-
51
- /**
52
- * Base interface that all LLM providers must implement
53
- */
54
- export interface LLMProvider {
55
- /**
56
- * Analyze content and detect external dependencies
57
- * @param content - Text content to analyze (README, code, etc.)
58
- * @param prompt - Detection prompt template
59
- * @returns LLM response with detected dependencies
60
- */
61
- analyze(content: string, prompt: string): Promise<LLMResponse>;
62
-
63
- /**
64
- * Get list of supported models for this provider
65
- */
66
- getSupportedModels(): string[];
67
-
68
- /**
69
- * Get current rate limit status
70
- */
71
- getRateLimit(): Promise<RateLimitInfo>;
72
-
73
- /**
74
- * Validate provider configuration
75
- */
76
- validateConfig(): boolean;
77
- }
78
-
79
- /**
80
- * Create an LLM provider instance
81
- */
82
- export function createLLMProvider(providerName: string, config: LLMProviderConfig): LLMProvider {
83
- // Implementation will be in specific provider files
84
- throw new Error(`Provider ${providerName} not yet implemented`);
85
- }
@@ -1,150 +0,0 @@
1
- /**
2
- * GitHub Copilot CLI Provider Implementation
3
- * Integrates with GitHub Copilot via CLI commands
4
- */
5
-
6
- import { execFile } from 'node:child_process';
7
- import { promisify } from 'node:util';
8
- import type {
9
- LLMProvider,
10
- LLMProviderConfig,
11
- LLMResponse,
12
- RateLimitInfo,
13
- DetectedDependency,
14
- LLMUsageMetadata
15
- } from './client.js';
16
- import { SYSTEM_PROMPT } from './prompts.js';
17
-
18
- const execFileAsync = promisify(execFile);
19
-
20
- export class GitHubCopilotProvider implements LLMProvider {
21
- private config: Required<LLMProviderConfig>;
22
- private model: string;
23
-
24
- constructor(config: LLMProviderConfig = {}) {
25
- // Default configuration for CLI-based approach
26
- this.config = {
27
- apiKey: config.apiKey || process.env['GITHUB_TOKEN'] || '',
28
- endpoint: config.endpoint || '',
29
- model: config.model || 'gpt-4',
30
- maxTokens: config.maxTokens || 4000,
31
- temperature: config.temperature || 0.3
32
- };
33
-
34
- this.model = this.config.model;
35
-
36
- // GitHub Copilot CLI uses GitHub authentication, not a separate API key
37
- // The GITHUB_TOKEN is used for authentication with GitHub, not OpenAI
38
- }
39
-
40
- async analyze(content: string, prompt: string): Promise<LLMResponse> {
41
- const startTime = Date.now();
42
-
43
- try {
44
- // Combine system prompt and user prompt for CLI
45
- const fullPrompt = `${SYSTEM_PROMPT}\n\n${prompt}`;
46
-
47
- // Use execFile to avoid shell escaping issues and command injection
48
- // Pass prompt directly as an argument without manual escaping
49
- const args = [
50
- 'copilot',
51
- '-p',
52
- fullPrompt,
53
- '--silent',
54
- '--allow-all-tools'
55
- ];
56
-
57
- const { stdout, stderr } = await execFileAsync('gh', args, {
58
- maxBuffer: 10 * 1024 * 1024, // 10MB buffer for large responses
59
- timeout: 60000 // 60 second timeout
60
- });
61
-
62
- const latencyMs = Date.now() - startTime;
63
-
64
- if (stderr && !stdout) {
65
- throw new Error(`Copilot CLI error: ${stderr}`);
66
- }
67
-
68
- // Try to parse the output as JSON
69
- // Copilot CLI may return the JSON directly or wrapped in markdown
70
- let content_text = stdout.trim();
71
-
72
- // Remove markdown code blocks if present
73
- if (content_text.includes('```json')) {
74
- const jsonMatch = content_text.match(/```json\s*([\s\S]*?)```/);
75
- if (jsonMatch && jsonMatch[1]) {
76
- content_text = jsonMatch[1].trim();
77
- }
78
- } else if (content_text.includes('```')) {
79
- const codeMatch = content_text.match(/```\s*([\s\S]*?)```/);
80
- if (codeMatch && codeMatch[1]) {
81
- content_text = codeMatch[1].trim();
82
- }
83
- }
84
-
85
- let parsed: { dependencies: DetectedDependency[] };
86
-
87
- try {
88
- parsed = JSON.parse(content_text);
89
- } catch (parseError) {
90
- console.error('Failed to parse Copilot CLI response:', content_text, parseError);
91
- // Return empty dependencies if parsing fails
92
- parsed = { dependencies: [] };
93
- }
94
-
95
- // Estimate token usage (rough approximation since CLI doesn't provide this)
96
- const estimatedTokens = Math.ceil(fullPrompt.length / 4) + Math.ceil(content_text.length / 4);
97
-
98
- const usage: LLMUsageMetadata = {
99
- promptTokens: Math.ceil(fullPrompt.length / 4),
100
- completionTokens: Math.ceil(content_text.length / 4),
101
- totalTokens: estimatedTokens,
102
- model: this.model,
103
- latencyMs
104
- };
105
-
106
- return {
107
- dependencies: parsed.dependencies || [],
108
- usage,
109
- rawResponse: content_text
110
- };
111
- } catch (error) {
112
- const latencyMs = Date.now() - startTime;
113
- console.error('Copilot CLI analysis failed:', error);
114
-
115
- // Return empty result on error
116
- return {
117
- dependencies: [],
118
- usage: {
119
- promptTokens: 0,
120
- completionTokens: 0,
121
- totalTokens: 0,
122
- model: this.model,
123
- latencyMs
124
- },
125
- rawResponse: error instanceof Error ? error.message : 'Unknown error'
126
- };
127
- }
128
- }
129
-
130
- getSupportedModels(): string[] {
131
- // Copilot CLI uses GitHub's models, not directly specified
132
- return ['github-copilot', 'gpt-4', 'gpt-4-turbo'];
133
- }
134
-
135
- async getRateLimit(): Promise<RateLimitInfo> {
136
- // Copilot CLI doesn't expose rate limits directly
137
- // Rate limiting is handled by GitHub's infrastructure
138
- return {
139
- remaining: -1, // Unknown
140
- limit: -1, // Unknown
141
- resetAt: new Date(0) // Unknown
142
- };
143
- }
144
-
145
- validateConfig(): boolean {
146
- // For CLI approach, we just need gh CLI to be available
147
- // Authentication is handled by GitHub CLI itself
148
- return true;
149
- }
150
- }
@@ -1,111 +0,0 @@
1
- /**
2
- * Detection prompts for LLM-based dependency analysis
3
- * Optimized for identifying external informational dependencies
4
- */
5
-
6
- export const SYSTEM_PROMPT = `You are an expert at analyzing code repositories to identify external informational dependencies.
7
-
8
- Your task is to identify external resources that developers reference but are NOT tracked by package managers (npm, PyPI, Cargo, etc.).
9
-
10
- INCLUDE these types of dependencies:
11
- - GitHub repositories referenced but not declared in package files
12
- - Documentation sites and API references
13
- - OpenAPI/GraphQL schemas
14
- - Research papers and arXiv preprints
15
- - Reference implementations and code examples
16
- - Technical specifications and RFCs
17
-
18
- EXCLUDE these (handled by dependabot):
19
- - NPM packages in package.json
20
- - Python packages in requirements.txt
21
- - Rust crates in Cargo.toml
22
- - Docker images in Dockerfile
23
- - Any declared package manager dependencies
24
-
25
- ALSO EXCLUDE (false positives):
26
- - URLs that reference the repository itself (self-references)
27
- - Relative file paths (e.g., CONTRIBUTING.md, docs/guide.md, ./src/utils)
28
- - Placeholder URLs used in documentation examples (example.com, example.org, localhost)
29
- - Internal documentation links within the same repository
30
- - URLs with template variables or placeholders (e.g., issues/[NUMBER], user/repo)
31
-
32
- Only return dependencies with confidence >= 0.7.
33
-
34
- For each dependency found, provide:
35
- 1. url: The complete URL
36
- 2. name: A descriptive name
37
- 3. description: What this dependency is used for
38
- 4. type: One of [reference-implementation, schema, documentation, research-paper, api-example, other]
39
- 5. confidence: A score from 0.0 to 1.0 indicating detection confidence
40
- 6. reasoning: Brief explanation of why this is a dependency
41
-
42
- Return ONLY valid JSON in this format:
43
- {
44
- "dependencies": [
45
- {
46
- "url": "https://example.com/resource",
47
- "name": "Resource Name",
48
- "description": "Purpose in the project",
49
- "type": "documentation",
50
- "confidence": 0.95,
51
- "reasoning": "Referenced in README as API documentation"
52
- }
53
- ]
54
- }`;
55
-
56
- export const DETECTION_PROMPT_TEMPLATE = `Analyze the following content from a code repository and identify external informational dependencies:
57
-
58
- ## Content Type: {contentType}
59
- ## File Path: {filePath}
60
-
61
- ## Content:
62
- {content}
63
-
64
- Remember:
65
- - Focus on external resources NOT in package managers
66
- - Provide confidence scores based on clarity of references
67
- - Include context about how each dependency is used
68
- - Return valid JSON only
69
-
70
- Analyze and respond:`;
71
-
72
- export function createDetectionPrompt(
73
- contentType: string,
74
- filePath: string,
75
- content: string
76
- ): string {
77
- return DETECTION_PROMPT_TEMPLATE.replace('{contentType}', contentType)
78
- .replace('{filePath}', filePath)
79
- .replace('{content}', content);
80
- }
81
-
82
- export const CLASSIFICATION_PROMPT_TEMPLATE = `Given this URL, classify its dependency type and suggest the best access method:
83
-
84
- URL: {url}
85
- Context: {context}
86
-
87
- Classify as one of:
88
- - reference-implementation: Example code demonstrating usage
89
- - schema: OpenAPI, JSON Schema, GraphQL, Protocol Buffers
90
- - documentation: API docs, tutorials, guides
91
- - research-paper: Academic papers, arXiv preprints
92
- - api-example: Code snippets from documentation
93
- - other: If none of the above fit
94
-
95
- Also determine the best access method:
96
- - github-api: For GitHub repositories
97
- - arxiv: For arXiv papers
98
- - openapi: For OpenAPI specifications
99
- - http: For generic web content
100
-
101
- Return JSON:
102
- {
103
- "type": "documentation",
104
- "accessMethod": "http",
105
- "confidence": 0.9,
106
- "reasoning": "URL structure suggests API documentation"
107
- }`;
108
-
109
- export function createClassificationPrompt(url: string, context: string): string {
110
- return CLASSIFICATION_PROMPT_TEMPLATE.replace('{url}', url).replace('{context}', context);
111
- }