@dependabit/action 0.1.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.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +225 -0
- package/action.yml +85 -0
- package/dist/actions/check.d.ts +33 -0
- package/dist/actions/check.d.ts.map +1 -0
- package/dist/actions/check.js +162 -0
- package/dist/actions/check.js.map +1 -0
- package/dist/actions/generate.d.ts +9 -0
- package/dist/actions/generate.d.ts.map +1 -0
- package/dist/actions/generate.js +152 -0
- package/dist/actions/generate.js.map +1 -0
- package/dist/actions/update.d.ts +9 -0
- package/dist/actions/update.d.ts.map +1 -0
- package/dist/actions/update.js +246 -0
- package/dist/actions/update.js.map +1 -0
- package/dist/actions/validate.d.ts +33 -0
- package/dist/actions/validate.d.ts.map +1 -0
- package/dist/actions/validate.js +226 -0
- package/dist/actions/validate.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +114 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +154 -0
- package/dist/logger.js.map +1 -0
- package/dist/utils/agent-config.d.ts +31 -0
- package/dist/utils/agent-config.d.ts.map +1 -0
- package/dist/utils/agent-config.js +42 -0
- package/dist/utils/agent-config.js.map +1 -0
- package/dist/utils/agent-router.d.ts +33 -0
- package/dist/utils/agent-router.d.ts.map +1 -0
- package/dist/utils/agent-router.js +57 -0
- package/dist/utils/agent-router.js.map +1 -0
- package/dist/utils/errors.d.ts +51 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +219 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/inputs.d.ts +35 -0
- package/dist/utils/inputs.d.ts.map +1 -0
- package/dist/utils/inputs.js +47 -0
- package/dist/utils/inputs.js.map +1 -0
- package/dist/utils/metrics.d.ts +66 -0
- package/dist/utils/metrics.d.ts.map +1 -0
- package/dist/utils/metrics.js +116 -0
- package/dist/utils/metrics.js.map +1 -0
- package/dist/utils/outputs.d.ts +43 -0
- package/dist/utils/outputs.d.ts.map +1 -0
- package/dist/utils/outputs.js +146 -0
- package/dist/utils/outputs.js.map +1 -0
- package/dist/utils/performance.d.ts +100 -0
- package/dist/utils/performance.d.ts.map +1 -0
- package/dist/utils/performance.js +185 -0
- package/dist/utils/performance.js.map +1 -0
- package/dist/utils/reporter.d.ts +43 -0
- package/dist/utils/reporter.d.ts.map +1 -0
- package/dist/utils/reporter.js +122 -0
- package/dist/utils/reporter.js.map +1 -0
- package/dist/utils/secrets.d.ts +45 -0
- package/dist/utils/secrets.d.ts.map +1 -0
- package/dist/utils/secrets.js +94 -0
- package/dist/utils/secrets.js.map +1 -0
- package/package.json +45 -0
- package/src/actions/check.ts +223 -0
- package/src/actions/generate.ts +181 -0
- package/src/actions/update.ts +284 -0
- package/src/actions/validate.ts +292 -0
- package/src/index.ts +43 -0
- package/src/logger.test.ts +200 -0
- package/src/logger.ts +210 -0
- package/src/utils/agent-config.ts +61 -0
- package/src/utils/agent-router.ts +67 -0
- package/src/utils/errors.ts +251 -0
- package/src/utils/inputs.ts +75 -0
- package/src/utils/metrics.ts +169 -0
- package/src/utils/outputs.ts +202 -0
- package/src/utils/performance.ts +248 -0
- package/src/utils/reporter.ts +169 -0
- package/src/utils/secrets.ts +124 -0
- package/test/actions/check.test.ts +216 -0
- package/test/actions/generate.test.ts +82 -0
- package/test/actions/update.test.ts +70 -0
- package/test/actions/validate.test.ts +257 -0
- package/test/utils/agent-config.test.ts +112 -0
- package/test/utils/agent-router.test.ts +129 -0
- package/test/utils/metrics.test.ts +221 -0
- package/test/utils/reporter.test.ts +196 -0
- package/test/utils/secrets.test.ts +217 -0
- package/tsconfig.json +15 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Severity } from '@dependabit/manifest';
|
|
2
|
+
import type { AgentAssignmentConfig } from './agent-config';
|
|
3
|
+
/**
|
|
4
|
+
* Route issue to appropriate AI agent based on severity
|
|
5
|
+
*
|
|
6
|
+
* Uses severity-to-agent mapping from configuration to determine
|
|
7
|
+
* which AI agent should be assigned to handle the issue.
|
|
8
|
+
*
|
|
9
|
+
* @param severity Change severity (breaking, major, minor)
|
|
10
|
+
* @param config Agent assignment configuration
|
|
11
|
+
* @returns Agent name (e.g., 'copilot', 'claude') or null if not configured
|
|
12
|
+
*/
|
|
13
|
+
export declare function routeToAgent(severity: Severity, config: AgentAssignmentConfig): string | null;
|
|
14
|
+
/**
|
|
15
|
+
* Generate assignee label for issue
|
|
16
|
+
*
|
|
17
|
+
* Creates a label in format "assigned:agent" that can be used
|
|
18
|
+
* to trigger agent-specific workflows or assign the issue.
|
|
19
|
+
*
|
|
20
|
+
* @param agent Agent name or null
|
|
21
|
+
* @returns Label string or null
|
|
22
|
+
*/
|
|
23
|
+
export declare function getAssigneeLabel(agent: string | null): string | null;
|
|
24
|
+
/**
|
|
25
|
+
* Get all configured agents
|
|
26
|
+
*
|
|
27
|
+
* Returns list of unique agent names configured in the severity mapping
|
|
28
|
+
*
|
|
29
|
+
* @param config Agent assignment configuration
|
|
30
|
+
* @returns Array of agent names
|
|
31
|
+
*/
|
|
32
|
+
export declare function getConfiguredAgents(config: AgentAssignmentConfig): string[];
|
|
33
|
+
//# sourceMappingURL=agent-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-router.d.ts","sourceRoot":"","sources":["../../src/utils/agent-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC5D;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CAO7F;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAMpE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,EAAE,CAoB3E"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route issue to appropriate AI agent based on severity
|
|
3
|
+
*
|
|
4
|
+
* Uses severity-to-agent mapping from configuration to determine
|
|
5
|
+
* which AI agent should be assigned to handle the issue.
|
|
6
|
+
*
|
|
7
|
+
* @param severity Change severity (breaking, major, minor)
|
|
8
|
+
* @param config Agent assignment configuration
|
|
9
|
+
* @returns Agent name (e.g., 'copilot', 'claude') or null if not configured
|
|
10
|
+
*/
|
|
11
|
+
export function routeToAgent(severity, config) {
|
|
12
|
+
if (!config.enabled) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const agent = config.severityMapping[severity];
|
|
16
|
+
return agent || null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generate assignee label for issue
|
|
20
|
+
*
|
|
21
|
+
* Creates a label in format "assigned:agent" that can be used
|
|
22
|
+
* to trigger agent-specific workflows or assign the issue.
|
|
23
|
+
*
|
|
24
|
+
* @param agent Agent name or null
|
|
25
|
+
* @returns Label string or null
|
|
26
|
+
*/
|
|
27
|
+
export function getAssigneeLabel(agent) {
|
|
28
|
+
if (!agent) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return `assigned:${agent}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get all configured agents
|
|
35
|
+
*
|
|
36
|
+
* Returns list of unique agent names configured in the severity mapping
|
|
37
|
+
*
|
|
38
|
+
* @param config Agent assignment configuration
|
|
39
|
+
* @returns Array of agent names
|
|
40
|
+
*/
|
|
41
|
+
export function getConfiguredAgents(config) {
|
|
42
|
+
if (!config.enabled) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
const agents = new Set();
|
|
46
|
+
if (config.severityMapping.breaking) {
|
|
47
|
+
agents.add(config.severityMapping.breaking);
|
|
48
|
+
}
|
|
49
|
+
if (config.severityMapping.major) {
|
|
50
|
+
agents.add(config.severityMapping.major);
|
|
51
|
+
}
|
|
52
|
+
if (config.severityMapping.minor) {
|
|
53
|
+
agents.add(config.severityMapping.minor);
|
|
54
|
+
}
|
|
55
|
+
return Array.from(agents);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=agent-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-router.js","sourceRoot":"","sources":["../../src/utils/agent-router.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB,EAAE,MAA6B,EAAiB;IAC7F,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,KAAK,IAAI,IAAI,CAAC;AAAA,CACtB;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAoB,EAAiB;IACpE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,YAAY,KAAK,EAAE,CAAC;AAAA,CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA6B,EAAY;IAC3E,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IAEjC,IAAI,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAAA,CAC3B"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error categorization and remediation messages
|
|
3
|
+
* Provides actionable error messages with remediation steps
|
|
4
|
+
*/
|
|
5
|
+
export declare enum ErrorCategory {
|
|
6
|
+
AUTHENTICATION = "authentication",
|
|
7
|
+
RATE_LIMIT = "rate_limit",
|
|
8
|
+
NETWORK = "network",
|
|
9
|
+
VALIDATION = "validation",
|
|
10
|
+
NOT_FOUND = "not_found",
|
|
11
|
+
PERMISSION = "permission",
|
|
12
|
+
CONFIGURATION = "configuration",
|
|
13
|
+
INTERNAL = "internal"
|
|
14
|
+
}
|
|
15
|
+
export interface CategorizedError {
|
|
16
|
+
category: ErrorCategory;
|
|
17
|
+
message: string;
|
|
18
|
+
originalError: Error;
|
|
19
|
+
remediation: string[];
|
|
20
|
+
context?: Record<string, unknown> | undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Error categorizer with remediation suggestions
|
|
24
|
+
*/
|
|
25
|
+
export declare class ErrorCategorizer {
|
|
26
|
+
/**
|
|
27
|
+
* Categorize an error and provide remediation steps
|
|
28
|
+
*/
|
|
29
|
+
categorize(error: Error, context?: Record<string, unknown>): CategorizedError;
|
|
30
|
+
/**
|
|
31
|
+
* Format error with remediation for display
|
|
32
|
+
*/
|
|
33
|
+
format(categorizedError: CategorizedError): string;
|
|
34
|
+
/**
|
|
35
|
+
* Check if error is retryable
|
|
36
|
+
*/
|
|
37
|
+
isRetryable(categorizedError: CategorizedError): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Get recommended retry delay in milliseconds
|
|
40
|
+
*/
|
|
41
|
+
getRetryDelay(categorizedError: CategorizedError): number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create a categorized error from an exception
|
|
45
|
+
*/
|
|
46
|
+
export declare function categorizeError(error: Error, context?: Record<string, unknown>): CategorizedError;
|
|
47
|
+
/**
|
|
48
|
+
* Format error with remediation steps
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatError(error: Error, context?: Record<string, unknown>): string;
|
|
51
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oBAAY,aAAa;IACvB,cAAc,mBAAmB;IACjC,UAAU,eAAe;IACzB,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,SAAS,cAAc;IACvB,UAAU,eAAe;IACzB,aAAa,kBAAkB;IAC/B,QAAQ,aAAa;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,KAAK,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC/C;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,CA8J5E;IAED;;OAEG;IACH,MAAM,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,MAAM,CAiBjD;IAED;;OAEG;IACH,WAAW,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAEvD;IAED;;OAEG;IACH,aAAa,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,MAAM,CASxD;CACF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,CAGjG;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAInF"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error categorization and remediation messages
|
|
3
|
+
* Provides actionable error messages with remediation steps
|
|
4
|
+
*/
|
|
5
|
+
export { ErrorCategory };
|
|
6
|
+
var ErrorCategory;
|
|
7
|
+
(function (ErrorCategory) {
|
|
8
|
+
ErrorCategory["AUTHENTICATION"] = "authentication";
|
|
9
|
+
ErrorCategory["RATE_LIMIT"] = "rate_limit";
|
|
10
|
+
ErrorCategory["NETWORK"] = "network";
|
|
11
|
+
ErrorCategory["VALIDATION"] = "validation";
|
|
12
|
+
ErrorCategory["NOT_FOUND"] = "not_found";
|
|
13
|
+
ErrorCategory["PERMISSION"] = "permission";
|
|
14
|
+
ErrorCategory["CONFIGURATION"] = "configuration";
|
|
15
|
+
ErrorCategory["INTERNAL"] = "internal";
|
|
16
|
+
})(ErrorCategory || (ErrorCategory = {}));
|
|
17
|
+
/**
|
|
18
|
+
* Error categorizer with remediation suggestions
|
|
19
|
+
*/
|
|
20
|
+
export class ErrorCategorizer {
|
|
21
|
+
/**
|
|
22
|
+
* Categorize an error and provide remediation steps
|
|
23
|
+
*/
|
|
24
|
+
categorize(error, context) {
|
|
25
|
+
const message = error.message.toLowerCase();
|
|
26
|
+
// Authentication errors
|
|
27
|
+
if (message.includes('authentication') ||
|
|
28
|
+
message.includes('unauthorized') ||
|
|
29
|
+
message.includes('invalid token') ||
|
|
30
|
+
message.includes('bad credentials')) {
|
|
31
|
+
return {
|
|
32
|
+
category: ErrorCategory.AUTHENTICATION,
|
|
33
|
+
message: error.message,
|
|
34
|
+
originalError: error,
|
|
35
|
+
remediation: [
|
|
36
|
+
'Verify that GITHUB_TOKEN is set correctly',
|
|
37
|
+
'Check token has required permissions (repo, issues, contents)',
|
|
38
|
+
'Ensure token has not expired',
|
|
39
|
+
'For fine-grained tokens, verify repository access is granted',
|
|
40
|
+
'Try regenerating the token if issues persist'
|
|
41
|
+
],
|
|
42
|
+
context
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// Rate limit errors
|
|
46
|
+
if (message.includes('rate limit') ||
|
|
47
|
+
message.includes('api rate limit exceeded') ||
|
|
48
|
+
message.includes('secondary rate limit')) {
|
|
49
|
+
return {
|
|
50
|
+
category: ErrorCategory.RATE_LIMIT,
|
|
51
|
+
message: error.message,
|
|
52
|
+
originalError: error,
|
|
53
|
+
remediation: [
|
|
54
|
+
'Wait for rate limit to reset (check X-RateLimit-Reset header)',
|
|
55
|
+
'Consider using authenticated requests (higher rate limits)',
|
|
56
|
+
'Implement request batching or caching',
|
|
57
|
+
'Review API usage patterns to reduce calls',
|
|
58
|
+
'For GitHub Actions, consider using GITHUB_TOKEN instead of PAT'
|
|
59
|
+
],
|
|
60
|
+
context
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Network errors
|
|
64
|
+
if (message.includes('econnrefused') ||
|
|
65
|
+
message.includes('enotfound') ||
|
|
66
|
+
message.includes('timeout') ||
|
|
67
|
+
message.includes('network')) {
|
|
68
|
+
return {
|
|
69
|
+
category: ErrorCategory.NETWORK,
|
|
70
|
+
message: error.message,
|
|
71
|
+
originalError: error,
|
|
72
|
+
remediation: [
|
|
73
|
+
'Check internet connectivity',
|
|
74
|
+
'Verify API endpoint is accessible',
|
|
75
|
+
'Check for firewall or proxy blocking requests',
|
|
76
|
+
'Retry the operation after a short delay',
|
|
77
|
+
'Verify DNS resolution is working'
|
|
78
|
+
],
|
|
79
|
+
context
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// Not found errors
|
|
83
|
+
if (message.includes('not found') || message.includes('404')) {
|
|
84
|
+
return {
|
|
85
|
+
category: ErrorCategory.NOT_FOUND,
|
|
86
|
+
message: error.message,
|
|
87
|
+
originalError: error,
|
|
88
|
+
remediation: [
|
|
89
|
+
'Verify the repository owner and name are correct',
|
|
90
|
+
'Check if the resource exists (branch, file, issue)',
|
|
91
|
+
'Ensure you have access to the repository (private repos)',
|
|
92
|
+
'Verify the URL or path is correct',
|
|
93
|
+
'Check if the resource was recently deleted'
|
|
94
|
+
],
|
|
95
|
+
context
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Permission errors
|
|
99
|
+
if (message.includes('permission') ||
|
|
100
|
+
message.includes('forbidden') ||
|
|
101
|
+
message.includes('403')) {
|
|
102
|
+
return {
|
|
103
|
+
category: ErrorCategory.PERMISSION,
|
|
104
|
+
message: error.message,
|
|
105
|
+
originalError: error,
|
|
106
|
+
remediation: [
|
|
107
|
+
'Verify token has required scopes (repo, admin:org, etc.)',
|
|
108
|
+
'Check repository access permissions',
|
|
109
|
+
'For organization repos, verify org membership',
|
|
110
|
+
'Ensure not attempting to modify protected branches',
|
|
111
|
+
'Review repository settings and branch protection rules'
|
|
112
|
+
],
|
|
113
|
+
context
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// Validation errors
|
|
117
|
+
if (message.includes('validation') ||
|
|
118
|
+
message.includes('invalid') ||
|
|
119
|
+
message.includes('malformed')) {
|
|
120
|
+
return {
|
|
121
|
+
category: ErrorCategory.VALIDATION,
|
|
122
|
+
message: error.message,
|
|
123
|
+
originalError: error,
|
|
124
|
+
remediation: [
|
|
125
|
+
'Check input data format and structure',
|
|
126
|
+
'Verify required fields are provided',
|
|
127
|
+
'Validate data types match API expectations',
|
|
128
|
+
'Review API documentation for correct format',
|
|
129
|
+
'Check for special characters that need escaping'
|
|
130
|
+
],
|
|
131
|
+
context
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// Configuration errors
|
|
135
|
+
if (message.includes('config') || message.includes('missing')) {
|
|
136
|
+
return {
|
|
137
|
+
category: ErrorCategory.CONFIGURATION,
|
|
138
|
+
message: error.message,
|
|
139
|
+
originalError: error,
|
|
140
|
+
remediation: [
|
|
141
|
+
'Verify all required configuration values are set',
|
|
142
|
+
'Check .dependabit/config.yml exists and is valid',
|
|
143
|
+
'Validate configuration schema',
|
|
144
|
+
'Review example configuration in documentation',
|
|
145
|
+
'Ensure environment variables are properly set'
|
|
146
|
+
],
|
|
147
|
+
context
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// Default to internal error
|
|
151
|
+
return {
|
|
152
|
+
category: ErrorCategory.INTERNAL,
|
|
153
|
+
message: error.message,
|
|
154
|
+
originalError: error,
|
|
155
|
+
remediation: [
|
|
156
|
+
'This may be an internal error or unexpected condition',
|
|
157
|
+
'Check error details for more information',
|
|
158
|
+
'Try running the operation again',
|
|
159
|
+
'If issue persists, report it with error details',
|
|
160
|
+
'Check GitHub status page for service issues'
|
|
161
|
+
],
|
|
162
|
+
context
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Format error with remediation for display
|
|
167
|
+
*/
|
|
168
|
+
format(categorizedError) {
|
|
169
|
+
const lines = [
|
|
170
|
+
`Error [${categorizedError.category}]: ${categorizedError.message}`,
|
|
171
|
+
'',
|
|
172
|
+
'Remediation steps:',
|
|
173
|
+
...categorizedError.remediation.map((step, i) => ` ${i + 1}. ${step}`)
|
|
174
|
+
];
|
|
175
|
+
if (categorizedError.context && Object.keys(categorizedError.context).length > 0) {
|
|
176
|
+
lines.push('');
|
|
177
|
+
lines.push('Context:');
|
|
178
|
+
for (const [key, value] of Object.entries(categorizedError.context)) {
|
|
179
|
+
lines.push(` ${key}: ${JSON.stringify(value)}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return lines.join('\n');
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Check if error is retryable
|
|
186
|
+
*/
|
|
187
|
+
isRetryable(categorizedError) {
|
|
188
|
+
return [ErrorCategory.NETWORK, ErrorCategory.RATE_LIMIT].includes(categorizedError.category);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get recommended retry delay in milliseconds
|
|
192
|
+
*/
|
|
193
|
+
getRetryDelay(categorizedError) {
|
|
194
|
+
switch (categorizedError.category) {
|
|
195
|
+
case ErrorCategory.RATE_LIMIT:
|
|
196
|
+
return 60000; // 1 minute
|
|
197
|
+
case ErrorCategory.NETWORK:
|
|
198
|
+
return 5000; // 5 seconds
|
|
199
|
+
default:
|
|
200
|
+
return 0; // Not retryable
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Create a categorized error from an exception
|
|
206
|
+
*/
|
|
207
|
+
export function categorizeError(error, context) {
|
|
208
|
+
const categorizer = new ErrorCategorizer();
|
|
209
|
+
return categorizer.categorize(error, context);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Format error with remediation steps
|
|
213
|
+
*/
|
|
214
|
+
export function formatError(error, context) {
|
|
215
|
+
const categorizer = new ErrorCategorizer();
|
|
216
|
+
const categorized = categorizer.categorize(error, context);
|
|
217
|
+
return categorizer.format(categorized);
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action Input Parsing
|
|
3
|
+
* Handles parsing and validation of GitHub Action inputs
|
|
4
|
+
*/
|
|
5
|
+
export interface GenerateActionInputs {
|
|
6
|
+
repoPath: string;
|
|
7
|
+
llmProvider: 'github-copilot' | 'claude' | 'openai';
|
|
8
|
+
llmModel?: string;
|
|
9
|
+
llmApiKey?: string;
|
|
10
|
+
manifestPath: string;
|
|
11
|
+
enableDebug: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface UpdateActionInputs {
|
|
14
|
+
repoPath: string;
|
|
15
|
+
manifestPath: string;
|
|
16
|
+
commits: string[];
|
|
17
|
+
}
|
|
18
|
+
export interface CheckActionInputs {
|
|
19
|
+
manifestPath: string;
|
|
20
|
+
createIssues: boolean;
|
|
21
|
+
issueLabels: string[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse inputs for the generate action
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseGenerateInputs(): GenerateActionInputs;
|
|
27
|
+
/**
|
|
28
|
+
* Parse inputs for the update action
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseUpdateInputs(): UpdateActionInputs;
|
|
31
|
+
/**
|
|
32
|
+
* Parse inputs for the check action
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseCheckInputs(): CheckActionInputs;
|
|
35
|
+
//# sourceMappingURL=inputs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputs.d.ts","sourceRoot":"","sources":["../../src/utils/inputs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,oBAAoB,CAa1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,kBAAkB,CAStD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,iBAAiB,CAWpD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action Input Parsing
|
|
3
|
+
* Handles parsing and validation of GitHub Action inputs
|
|
4
|
+
*/
|
|
5
|
+
import * as core from '@actions/core';
|
|
6
|
+
/**
|
|
7
|
+
* Parse inputs for the generate action
|
|
8
|
+
*/
|
|
9
|
+
export function parseGenerateInputs() {
|
|
10
|
+
const llmModelInput = core.getInput('llm_model');
|
|
11
|
+
const llmApiKeyInput = core.getInput('llm_api_key') || process.env['GITHUB_TOKEN'] || process.env['OPENAI_API_KEY'];
|
|
12
|
+
return {
|
|
13
|
+
repoPath: core.getInput('repo_path') || process.cwd(),
|
|
14
|
+
llmProvider: (core.getInput('llm_provider') || 'github-copilot'),
|
|
15
|
+
...(llmModelInput && { llmModel: llmModelInput }),
|
|
16
|
+
...(llmApiKeyInput && { llmApiKey: llmApiKeyInput }),
|
|
17
|
+
manifestPath: core.getInput('manifest_path') || '.dependabit/manifest.json',
|
|
18
|
+
enableDebug: core.getInput('debug') === 'true'
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse inputs for the update action
|
|
23
|
+
*/
|
|
24
|
+
export function parseUpdateInputs() {
|
|
25
|
+
const commitsInput = core.getInput('commits');
|
|
26
|
+
const commits = commitsInput ? commitsInput.split(',').map((c) => c.trim()) : [];
|
|
27
|
+
return {
|
|
28
|
+
repoPath: core.getInput('repo_path') || process.cwd(),
|
|
29
|
+
manifestPath: core.getInput('manifest_path') || '.dependabit/manifest.json',
|
|
30
|
+
commits
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parse inputs for the check action
|
|
35
|
+
*/
|
|
36
|
+
export function parseCheckInputs() {
|
|
37
|
+
const labelsInput = core.getInput('issue_labels');
|
|
38
|
+
const labels = labelsInput
|
|
39
|
+
? labelsInput.split(',').map((l) => l.trim())
|
|
40
|
+
: ['dependabit', 'dependency-update'];
|
|
41
|
+
return {
|
|
42
|
+
manifestPath: core.getInput('manifest_path') || '.dependabit/manifest.json',
|
|
43
|
+
createIssues: core.getBooleanInput('create_issues') !== false,
|
|
44
|
+
issueLabels: labels
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=inputs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputs.js","sourceRoot":"","sources":["../../src/utils/inputs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,IAAI,MAAM,eAAe,CAAC;AAuBtC;;GAEG;AACH,MAAM,UAAU,mBAAmB,GAAyB;IAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjD,MAAM,cAAc,GAClB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAE/F,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE;QACrD,WAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,gBAAgB,CAAqB;QACpF,GAAG,CAAC,aAAa,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;QACjD,GAAG,CAAC,cAAc,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;QACpD,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,2BAA2B;QAC3E,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,MAAM;KAC/C,CAAC;AAAA,CACH;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,GAAuB;IACtD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEjF,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE;QACrD,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,2BAA2B;QAC3E,OAAO;KACR,CAAC;AAAA,CACH;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,GAAsB;IACpD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,WAAW;QACxB,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7C,CAAC,CAAC,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;IAExC,OAAO;QACL,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,2BAA2B;QAC3E,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,KAAK,KAAK;QAC7D,WAAW,EAAE,MAAM;KACpB,CAAC;AAAA,CACH"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics calculator for false positive rate tracking
|
|
3
|
+
* Implements 30-day rolling window analysis and trend detection
|
|
4
|
+
*/
|
|
5
|
+
export interface MetricsConfig {
|
|
6
|
+
windowDays?: number;
|
|
7
|
+
threshold?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface FeedbackSummary {
|
|
10
|
+
truePositives: number;
|
|
11
|
+
falsePositives: number;
|
|
12
|
+
total: number;
|
|
13
|
+
}
|
|
14
|
+
export interface DataPoint {
|
|
15
|
+
date: string;
|
|
16
|
+
falsePositiveRate: number;
|
|
17
|
+
}
|
|
18
|
+
export interface Trend {
|
|
19
|
+
direction: 'improving' | 'worsening' | 'stable' | 'no-data';
|
|
20
|
+
slope: number;
|
|
21
|
+
}
|
|
22
|
+
export interface ThresholdCheck {
|
|
23
|
+
passed: boolean;
|
|
24
|
+
rate: number;
|
|
25
|
+
threshold: number;
|
|
26
|
+
}
|
|
27
|
+
export interface MetricsReport {
|
|
28
|
+
currentRate: number;
|
|
29
|
+
rollingAverage: number;
|
|
30
|
+
trend: Trend;
|
|
31
|
+
thresholdCheck: ThresholdCheck;
|
|
32
|
+
totalFeedback: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Calculator for false positive metrics with rolling window analysis
|
|
36
|
+
*/
|
|
37
|
+
export declare class MetricsCalculator {
|
|
38
|
+
private windowDays;
|
|
39
|
+
private threshold;
|
|
40
|
+
constructor(config?: MetricsConfig);
|
|
41
|
+
/**
|
|
42
|
+
* Calculate false positive rate from feedback data
|
|
43
|
+
*/
|
|
44
|
+
calculateFalsePositiveRate(feedback: FeedbackSummary): number;
|
|
45
|
+
/**
|
|
46
|
+
* Calculate rolling average over the time window
|
|
47
|
+
*/
|
|
48
|
+
calculateRollingAverage(dataPoints: DataPoint[], windowDays?: number, referenceDate?: Date): number;
|
|
49
|
+
/**
|
|
50
|
+
* Detect trend direction using linear regression
|
|
51
|
+
*/
|
|
52
|
+
getTrend(dataPoints: DataPoint[]): Trend;
|
|
53
|
+
/**
|
|
54
|
+
* Check if rate is within acceptable threshold
|
|
55
|
+
*/
|
|
56
|
+
checkThreshold(rate: number, threshold?: number): ThresholdCheck;
|
|
57
|
+
/**
|
|
58
|
+
* Generate comprehensive metrics report
|
|
59
|
+
*/
|
|
60
|
+
generateReport(currentFeedback: FeedbackSummary, history: DataPoint[]): MetricsReport;
|
|
61
|
+
/**
|
|
62
|
+
* Format rate as percentage string
|
|
63
|
+
*/
|
|
64
|
+
formatRate(rate: number): string;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/utils/metrics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,KAAK;IACpB,SAAS,EAAE,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC5D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAE1B,YAAY,MAAM,GAAE,aAAkB,EAGrC;IAED;;OAEG;IACH,0BAA0B,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAK5D;IAED;;OAEG;IACH,uBAAuB,CACrB,UAAU,EAAE,SAAS,EAAE,EACvB,UAAU,CAAC,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,IAAI,GACnB,MAAM,CAkBR;IAED;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,CAsCvC;IAED;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,CAO/D;IAED;;OAEG;IACH,cAAc,CAAC,eAAe,EAAE,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,aAAa,CAapF;IAED;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/B;CACF"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics calculator for false positive rate tracking
|
|
3
|
+
* Implements 30-day rolling window analysis and trend detection
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Calculator for false positive metrics with rolling window analysis
|
|
7
|
+
*/
|
|
8
|
+
export class MetricsCalculator {
|
|
9
|
+
windowDays;
|
|
10
|
+
threshold;
|
|
11
|
+
constructor(config = {}) {
|
|
12
|
+
this.windowDays = config.windowDays || 30;
|
|
13
|
+
this.threshold = config.threshold || 0.1; // 10% default threshold
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Calculate false positive rate from feedback data
|
|
17
|
+
*/
|
|
18
|
+
calculateFalsePositiveRate(feedback) {
|
|
19
|
+
if (feedback.total === 0) {
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
return feedback.falsePositives / feedback.total;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Calculate rolling average over the time window
|
|
26
|
+
*/
|
|
27
|
+
calculateRollingAverage(dataPoints, windowDays, referenceDate) {
|
|
28
|
+
const days = windowDays || this.windowDays;
|
|
29
|
+
const endDate = referenceDate || new Date();
|
|
30
|
+
const startDate = new Date(endDate);
|
|
31
|
+
startDate.setDate(startDate.getDate() - days);
|
|
32
|
+
// Filter data points within the window
|
|
33
|
+
const windowData = dataPoints.filter((point) => {
|
|
34
|
+
const pointDate = new Date(point.date);
|
|
35
|
+
return pointDate >= startDate && pointDate <= endDate;
|
|
36
|
+
});
|
|
37
|
+
if (windowData.length === 0) {
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
const sum = windowData.reduce((acc, point) => acc + point.falsePositiveRate, 0);
|
|
41
|
+
return sum / windowData.length;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Detect trend direction using linear regression
|
|
45
|
+
*/
|
|
46
|
+
getTrend(dataPoints) {
|
|
47
|
+
if (dataPoints.length < 2) {
|
|
48
|
+
return { direction: 'no-data', slope: 0 };
|
|
49
|
+
}
|
|
50
|
+
// Simple linear regression
|
|
51
|
+
const n = dataPoints.length;
|
|
52
|
+
let sumX = 0;
|
|
53
|
+
let sumY = 0;
|
|
54
|
+
let sumXY = 0;
|
|
55
|
+
let sumX2 = 0;
|
|
56
|
+
dataPoints.forEach((point, index) => {
|
|
57
|
+
const x = index;
|
|
58
|
+
const y = point.falsePositiveRate;
|
|
59
|
+
sumX += x;
|
|
60
|
+
sumY += y;
|
|
61
|
+
sumXY += x * y;
|
|
62
|
+
sumX2 += x * x;
|
|
63
|
+
});
|
|
64
|
+
const denominator = n * sumX2 - sumX * sumX;
|
|
65
|
+
if (denominator === 0) {
|
|
66
|
+
return { direction: 'no-data', slope: 0 };
|
|
67
|
+
}
|
|
68
|
+
const slope = (n * sumXY - sumX * sumY) / denominator;
|
|
69
|
+
// Determine direction based on slope
|
|
70
|
+
let direction;
|
|
71
|
+
if (Math.abs(slope) < 0.001) {
|
|
72
|
+
direction = 'stable';
|
|
73
|
+
}
|
|
74
|
+
else if (slope < 0) {
|
|
75
|
+
direction = 'improving';
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
direction = 'worsening';
|
|
79
|
+
}
|
|
80
|
+
return { direction, slope };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if rate is within acceptable threshold
|
|
84
|
+
*/
|
|
85
|
+
checkThreshold(rate, threshold) {
|
|
86
|
+
const targetThreshold = threshold !== undefined ? threshold : this.threshold;
|
|
87
|
+
return {
|
|
88
|
+
passed: rate <= targetThreshold,
|
|
89
|
+
rate,
|
|
90
|
+
threshold: targetThreshold
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Generate comprehensive metrics report
|
|
95
|
+
*/
|
|
96
|
+
generateReport(currentFeedback, history) {
|
|
97
|
+
const currentRate = this.calculateFalsePositiveRate(currentFeedback);
|
|
98
|
+
const rollingAverage = this.calculateRollingAverage(history);
|
|
99
|
+
const trend = this.getTrend(history);
|
|
100
|
+
const thresholdCheck = this.checkThreshold(rollingAverage);
|
|
101
|
+
return {
|
|
102
|
+
currentRate,
|
|
103
|
+
rollingAverage,
|
|
104
|
+
trend,
|
|
105
|
+
thresholdCheck,
|
|
106
|
+
totalFeedback: currentFeedback.total
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Format rate as percentage string
|
|
111
|
+
*/
|
|
112
|
+
formatRate(rate) {
|
|
113
|
+
return `${(rate * 100).toFixed(1)}%`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=metrics.js.map
|