contradiction-mcp 0.1.0
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/LICENSE +21 -0
- package/README.md +536 -0
- package/bin/cli.js +182 -0
- package/dist/analysis/claimMatcher.d.ts +48 -0
- package/dist/analysis/claimMatcher.js +131 -0
- package/dist/analysis/claimMatcher.js.map +1 -0
- package/dist/analysis/claimRelationship.d.ts +15 -0
- package/dist/analysis/claimRelationship.js +12 -0
- package/dist/analysis/claimRelationship.js.map +1 -0
- package/dist/analysis/confidenceScorer.d.ts +40 -0
- package/dist/analysis/confidenceScorer.js +59 -0
- package/dist/analysis/confidenceScorer.js.map +1 -0
- package/dist/analysis/contextAnalyzer.d.ts +13 -0
- package/dist/analysis/contextAnalyzer.js +187 -0
- package/dist/analysis/contextAnalyzer.js.map +1 -0
- package/dist/analysis/contradictionClassifier.d.ts +16 -0
- package/dist/analysis/contradictionClassifier.js +141 -0
- package/dist/analysis/contradictionClassifier.js.map +1 -0
- package/dist/analysis/contradictionEngine.d.ts +29 -0
- package/dist/analysis/contradictionEngine.js +284 -0
- package/dist/analysis/contradictionEngine.js.map +1 -0
- package/dist/analysis/explanationBuilder.d.ts +36 -0
- package/dist/analysis/explanationBuilder.js +77 -0
- package/dist/analysis/explanationBuilder.js.map +1 -0
- package/dist/analysis/valueComparator.d.ts +38 -0
- package/dist/analysis/valueComparator.js +418 -0
- package/dist/analysis/valueComparator.js.map +1 -0
- package/dist/config/env.d.ts +46 -0
- package/dist/config/env.js +34 -0
- package/dist/config/env.js.map +1 -0
- package/dist/connectors/base/connectorUtils.d.ts +26 -0
- package/dist/connectors/base/connectorUtils.js +63 -0
- package/dist/connectors/base/connectorUtils.js.map +1 -0
- package/dist/connectors/base/security.d.ts +11 -0
- package/dist/connectors/base/security.js +9 -0
- package/dist/connectors/base/security.js.map +1 -0
- package/dist/connectors/connectorRegistry.d.ts +43 -0
- package/dist/connectors/connectorRegistry.js +91 -0
- package/dist/connectors/connectorRegistry.js.map +1 -0
- package/dist/connectors/document/documentConnector.d.ts +45 -0
- package/dist/connectors/document/documentConnector.js +410 -0
- package/dist/connectors/document/documentConnector.js.map +1 -0
- package/dist/connectors/github/githubClient.d.ts +52 -0
- package/dist/connectors/github/githubClient.js +207 -0
- package/dist/connectors/github/githubClient.js.map +1 -0
- package/dist/connectors/github/githubConnector.d.ts +26 -0
- package/dist/connectors/github/githubConnector.js +169 -0
- package/dist/connectors/github/githubConnector.js.map +1 -0
- package/dist/connectors/github/githubExtractor.d.ts +26 -0
- package/dist/connectors/github/githubExtractor.js +469 -0
- package/dist/connectors/github/githubExtractor.js.map +1 -0
- package/dist/connectors/github/githubNormalizer.d.ts +11 -0
- package/dist/connectors/github/githubNormalizer.js +24 -0
- package/dist/connectors/github/githubNormalizer.js.map +1 -0
- package/dist/connectors/github/githubTypes.d.ts +55 -0
- package/dist/connectors/github/githubTypes.js +2 -0
- package/dist/connectors/github/githubTypes.js.map +1 -0
- package/dist/connectors/syncService.d.ts +60 -0
- package/dist/connectors/syncService.js +176 -0
- package/dist/connectors/syncService.js.map +1 -0
- package/dist/connectors/types/connector.d.ts +34 -0
- package/dist/connectors/types/connector.js +2 -0
- package/dist/connectors/types/connector.js.map +1 -0
- package/dist/connectors/types/fetchResult.d.ts +39 -0
- package/dist/connectors/types/fetchResult.js +2 -0
- package/dist/connectors/types/fetchResult.js.map +1 -0
- package/dist/connectors/website/ssrfGuard.d.ts +11 -0
- package/dist/connectors/website/ssrfGuard.js +122 -0
- package/dist/connectors/website/ssrfGuard.js.map +1 -0
- package/dist/connectors/website/websiteConnector.d.ts +30 -0
- package/dist/connectors/website/websiteConnector.js +231 -0
- package/dist/connectors/website/websiteConnector.js.map +1 -0
- package/dist/discovery/candidateGenerator.d.ts +12 -0
- package/dist/discovery/candidateGenerator.js +110 -0
- package/dist/discovery/candidateGenerator.js.map +1 -0
- package/dist/discovery/contradictionScanner.d.ts +30 -0
- package/dist/discovery/contradictionScanner.js +47 -0
- package/dist/discovery/contradictionScanner.js.map +1 -0
- package/dist/discovery/discoveryService.d.ts +37 -0
- package/dist/discovery/discoveryService.js +131 -0
- package/dist/discovery/discoveryService.js.map +1 -0
- package/dist/discovery/rankingService.d.ts +34 -0
- package/dist/discovery/rankingService.js +52 -0
- package/dist/discovery/rankingService.js.map +1 -0
- package/dist/discovery/similarityIndex.d.ts +20 -0
- package/dist/discovery/similarityIndex.js +89 -0
- package/dist/discovery/similarityIndex.js.map +1 -0
- package/dist/domain/entities/claim.d.ts +99 -0
- package/dist/domain/entities/claim.js +92 -0
- package/dist/domain/entities/claim.js.map +1 -0
- package/dist/domain/entities/contradiction.d.ts +110 -0
- package/dist/domain/entities/contradiction.js +74 -0
- package/dist/domain/entities/contradiction.js.map +1 -0
- package/dist/domain/entities/source.d.ts +43 -0
- package/dist/domain/entities/source.js +35 -0
- package/dist/domain/entities/source.js.map +1 -0
- package/dist/domain/types/common.d.ts +46 -0
- package/dist/domain/types/common.js +74 -0
- package/dist/domain/types/common.js.map +1 -0
- package/dist/httpServer.d.ts +25 -0
- package/dist/httpServer.js +164 -0
- package/dist/httpServer.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -0
- package/dist/intelligence/authorityScorer.d.ts +20 -0
- package/dist/intelligence/authorityScorer.js +103 -0
- package/dist/intelligence/authorityScorer.js.map +1 -0
- package/dist/intelligence/entityResolver.d.ts +33 -0
- package/dist/intelligence/entityResolver.js +152 -0
- package/dist/intelligence/entityResolver.js.map +1 -0
- package/dist/intelligence/evidenceEvaluator.d.ts +15 -0
- package/dist/intelligence/evidenceEvaluator.js +63 -0
- package/dist/intelligence/evidenceEvaluator.js.map +1 -0
- package/dist/intelligence/freshnessScorer.d.ts +25 -0
- package/dist/intelligence/freshnessScorer.js +90 -0
- package/dist/intelligence/freshnessScorer.js.map +1 -0
- package/dist/intelligence/provenanceAnalyzer.d.ts +19 -0
- package/dist/intelligence/provenanceAnalyzer.js +33 -0
- package/dist/intelligence/provenanceAnalyzer.js.map +1 -0
- package/dist/intelligence/resolutionAdvisor.d.ts +40 -0
- package/dist/intelligence/resolutionAdvisor.js +118 -0
- package/dist/intelligence/resolutionAdvisor.js.map +1 -0
- package/dist/intelligence/semanticMatcher.d.ts +21 -0
- package/dist/intelligence/semanticMatcher.js +71 -0
- package/dist/intelligence/semanticMatcher.js.map +1 -0
- package/dist/scripts/comprehensiveVerification.d.ts +5 -0
- package/dist/scripts/comprehensiveVerification.js +961 -0
- package/dist/scripts/comprehensiveVerification.js.map +1 -0
- package/dist/scripts/finalLiveDemo.d.ts +5 -0
- package/dist/scripts/finalLiveDemo.js +226 -0
- package/dist/scripts/finalLiveDemo.js.map +1 -0
- package/dist/scripts/liveMcpSmoke.d.ts +1 -0
- package/dist/scripts/liveMcpSmoke.js +89 -0
- package/dist/scripts/liveMcpSmoke.js.map +1 -0
- package/dist/scripts/seedDemoData.d.ts +6 -0
- package/dist/scripts/seedDemoData.js +179 -0
- package/dist/scripts/seedDemoData.js.map +1 -0
- package/dist/server.d.ts +28 -0
- package/dist/server.js +1264 -0
- package/dist/server.js.map +1 -0
- package/dist/services/analysisService.d.ts +40 -0
- package/dist/services/analysisService.js +65 -0
- package/dist/services/analysisService.js.map +1 -0
- package/dist/services/healthService.d.ts +42 -0
- package/dist/services/healthService.js +50 -0
- package/dist/services/healthService.js.map +1 -0
- package/dist/services/metricsService.d.ts +35 -0
- package/dist/services/metricsService.js +57 -0
- package/dist/services/metricsService.js.map +1 -0
- package/dist/services/rateLimiter.d.ts +23 -0
- package/dist/services/rateLimiter.js +45 -0
- package/dist/services/rateLimiter.js.map +1 -0
- package/dist/services/reviewService.d.ts +32 -0
- package/dist/services/reviewService.js +94 -0
- package/dist/services/reviewService.js.map +1 -0
- package/dist/services/schedulerService.d.ts +30 -0
- package/dist/services/schedulerService.js +89 -0
- package/dist/services/schedulerService.js.map +1 -0
- package/dist/storage/backupService.d.ts +14 -0
- package/dist/storage/backupService.js +90 -0
- package/dist/storage/backupService.js.map +1 -0
- package/dist/storage/database.d.ts +119 -0
- package/dist/storage/database.js +935 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/migrations/001_initial.sql +63 -0
- package/dist/storage/migrations/002_discovery_uniqueness.sql +8 -0
- package/dist/storage/migrations/003_connector_identity.sql +7 -0
- package/dist/storage/migrations/004_claim_context.sql +15 -0
- package/dist/storage/migrations/005_claim_history.sql +26 -0
- package/dist/storage/migrations/006_contradiction_resolution.sql +27 -0
- package/dist/utils/logger.d.ts +20 -0
- package/dist/utils/logger.js +48 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const StandardSourceTypes = [
|
|
3
|
+
'github',
|
|
4
|
+
'document',
|
|
5
|
+
'email',
|
|
6
|
+
'calendar',
|
|
7
|
+
'spreadsheet',
|
|
8
|
+
'database',
|
|
9
|
+
'website',
|
|
10
|
+
'crm',
|
|
11
|
+
'manual',
|
|
12
|
+
];
|
|
13
|
+
export const SourceSchema = z.object({
|
|
14
|
+
id: z.string().min(1),
|
|
15
|
+
externalId: z.string().nullable().optional(),
|
|
16
|
+
type: z.string().min(1),
|
|
17
|
+
name: z.string().min(1),
|
|
18
|
+
uri: z.string().nullable().optional(),
|
|
19
|
+
lastFetchedAt: z.coerce.date().nullable().optional(),
|
|
20
|
+
createdAt: z.coerce.date(),
|
|
21
|
+
updatedAt: z.coerce.date(),
|
|
22
|
+
trustScore: z.number().min(0.0).max(1.0).default(1.0),
|
|
23
|
+
metadata: z.record(z.string(), z.unknown()).default({}),
|
|
24
|
+
});
|
|
25
|
+
export const CreateSourceInputSchema = z.object({
|
|
26
|
+
id: z.string().min(1).optional(),
|
|
27
|
+
externalId: z.string().nullable().optional(),
|
|
28
|
+
type: z.string().min(1),
|
|
29
|
+
name: z.string().min(1),
|
|
30
|
+
uri: z.string().nullable().optional(),
|
|
31
|
+
lastFetchedAt: z.coerce.date().nullable().optional(),
|
|
32
|
+
trustScore: z.number().min(0.0).max(1.0).default(1.0).optional(),
|
|
33
|
+
metadata: z.record(z.string(), z.unknown()).default({}).optional(),
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.js","sourceRoot":"","sources":["../../../src/domain/entities/source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,QAAQ;IACR,UAAU;IACV,OAAO;IACP,UAAU;IACV,aAAa;IACb,UAAU;IACV,SAAS;IACT,KAAK;IACL,QAAQ;CACA,CAAC;AAkBX,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC5C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACrC,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACpD,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE;IAC1B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;IACrD,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACxD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC5C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACrC,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACpD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAChE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;CACnE,CAAC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type EntityId = string;
|
|
2
|
+
export type ISODateString = string;
|
|
3
|
+
export interface Timestamps {
|
|
4
|
+
createdAt: Date;
|
|
5
|
+
updatedAt?: Date;
|
|
6
|
+
}
|
|
7
|
+
export type JsonValue = string | number | boolean | null | {
|
|
8
|
+
[key: string]: JsonValue;
|
|
9
|
+
} | JsonValue[];
|
|
10
|
+
export type Metadata = Record<string, unknown>;
|
|
11
|
+
export declare class ContradictionError extends Error {
|
|
12
|
+
readonly code: string;
|
|
13
|
+
readonly isOperational: boolean;
|
|
14
|
+
readonly details?: unknown;
|
|
15
|
+
constructor(message: string, code?: string, isOperational?: boolean, details?: unknown);
|
|
16
|
+
toSafeObject(): {
|
|
17
|
+
code: string;
|
|
18
|
+
message: string;
|
|
19
|
+
details?: unknown;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export declare class ValidationError extends ContradictionError {
|
|
23
|
+
constructor(message: string, details?: unknown);
|
|
24
|
+
}
|
|
25
|
+
export declare class NotFoundError extends ContradictionError {
|
|
26
|
+
constructor(entityName: string, id: string);
|
|
27
|
+
}
|
|
28
|
+
export declare class DatabaseError extends ContradictionError {
|
|
29
|
+
constructor(message: string, details?: unknown);
|
|
30
|
+
}
|
|
31
|
+
export declare class ConfigurationError extends ContradictionError {
|
|
32
|
+
constructor(message: string);
|
|
33
|
+
}
|
|
34
|
+
export declare class AuthenticationError extends ContradictionError {
|
|
35
|
+
constructor(message: string, details?: unknown);
|
|
36
|
+
}
|
|
37
|
+
export declare class AuthorizationError extends ContradictionError {
|
|
38
|
+
constructor(message: string, details?: unknown);
|
|
39
|
+
}
|
|
40
|
+
export declare class ConnectorError extends ContradictionError {
|
|
41
|
+
constructor(message: string, details?: unknown);
|
|
42
|
+
}
|
|
43
|
+
export declare function toSafeError(error: unknown): {
|
|
44
|
+
code: string;
|
|
45
|
+
message: string;
|
|
46
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export class ContradictionError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
isOperational;
|
|
4
|
+
details;
|
|
5
|
+
constructor(message, code = 'INTERNAL_ERROR', isOperational = true, details) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = this.constructor.name;
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.isOperational = isOperational;
|
|
10
|
+
this.details = details;
|
|
11
|
+
Error.captureStackTrace(this, this.constructor);
|
|
12
|
+
}
|
|
13
|
+
toSafeObject() {
|
|
14
|
+
return {
|
|
15
|
+
code: this.code,
|
|
16
|
+
message: this.message,
|
|
17
|
+
...(this.details ? { details: this.details } : {}),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class ValidationError extends ContradictionError {
|
|
22
|
+
constructor(message, details) {
|
|
23
|
+
super(message, 'VALIDATION_ERROR', true, details);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class NotFoundError extends ContradictionError {
|
|
27
|
+
constructor(entityName, id) {
|
|
28
|
+
super(`${entityName} with id '${id}' not found`, 'NOT_FOUND', true, { entityName, id });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class DatabaseError extends ContradictionError {
|
|
32
|
+
constructor(message, details) {
|
|
33
|
+
super(message, 'DATABASE_ERROR', true, details);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export class ConfigurationError extends ContradictionError {
|
|
37
|
+
constructor(message) {
|
|
38
|
+
super(message, 'CONFIGURATION_ERROR', false);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export class AuthenticationError extends ContradictionError {
|
|
42
|
+
constructor(message, details) {
|
|
43
|
+
super(message, 'AUTHENTICATION_ERROR', true, details);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export class AuthorizationError extends ContradictionError {
|
|
47
|
+
constructor(message, details) {
|
|
48
|
+
super(message, 'AUTHORIZATION_ERROR', true, details);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export class ConnectorError extends ContradictionError {
|
|
52
|
+
constructor(message, details) {
|
|
53
|
+
super(message, 'CONNECTOR_ERROR', true, details);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function toSafeError(error) {
|
|
57
|
+
if (error instanceof ContradictionError && error.isOperational) {
|
|
58
|
+
return {
|
|
59
|
+
code: error.code,
|
|
60
|
+
message: error.message,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (error instanceof Error) {
|
|
64
|
+
return {
|
|
65
|
+
code: 'INTERNAL_ERROR',
|
|
66
|
+
message: error.message,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
code: 'UNKNOWN_ERROR',
|
|
71
|
+
message: String(error),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/domain/types/common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/server';
|
|
2
|
+
import { RateLimiter } from './services/rateLimiter.js';
|
|
3
|
+
import { HealthService } from './services/healthService.js';
|
|
4
|
+
export interface HttpServerOptions {
|
|
5
|
+
server: McpServer;
|
|
6
|
+
healthService: HealthService;
|
|
7
|
+
port: number;
|
|
8
|
+
host: string;
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
rateLimiter?: RateLimiter;
|
|
11
|
+
}
|
|
12
|
+
export declare class McpHttpServer {
|
|
13
|
+
private httpServer;
|
|
14
|
+
private readonly server;
|
|
15
|
+
private readonly healthService;
|
|
16
|
+
private readonly port;
|
|
17
|
+
private readonly host;
|
|
18
|
+
private readonly apiKey?;
|
|
19
|
+
private readonly rateLimiter;
|
|
20
|
+
private transport;
|
|
21
|
+
constructor(options: HttpServerOptions);
|
|
22
|
+
start(): Promise<void>;
|
|
23
|
+
getPort(): number;
|
|
24
|
+
stop(): Promise<void>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import { NodeStreamableHTTPServerTransport, localhostHostValidation, localhostOriginValidation, } from '@modelcontextprotocol/node';
|
|
3
|
+
import { RateLimiter, RateLimitExceededError } from './services/rateLimiter.js';
|
|
4
|
+
import { globalMetrics } from './services/metricsService.js';
|
|
5
|
+
import { logger } from './utils/logger.js';
|
|
6
|
+
export class McpHttpServer {
|
|
7
|
+
httpServer = null;
|
|
8
|
+
server;
|
|
9
|
+
healthService;
|
|
10
|
+
port;
|
|
11
|
+
host;
|
|
12
|
+
apiKey;
|
|
13
|
+
rateLimiter;
|
|
14
|
+
transport = null;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.server = options.server;
|
|
17
|
+
this.healthService = options.healthService;
|
|
18
|
+
this.port = options.port;
|
|
19
|
+
this.host = options.host;
|
|
20
|
+
this.apiKey = options.apiKey;
|
|
21
|
+
this.rateLimiter = options.rateLimiter ?? new RateLimiter({ windowMs: 60000, maxRequests: 60 });
|
|
22
|
+
}
|
|
23
|
+
async start() {
|
|
24
|
+
this.transport = new NodeStreamableHTTPServerTransport({
|
|
25
|
+
sessionIdGenerator: undefined, // stateless Streamable HTTP
|
|
26
|
+
});
|
|
27
|
+
await this.server.connect(this.transport);
|
|
28
|
+
const validateHost = localhostHostValidation();
|
|
29
|
+
const validateOrigin = localhostOriginValidation();
|
|
30
|
+
this.httpServer = http.createServer(async (req, res) => {
|
|
31
|
+
const startTime = performance.now();
|
|
32
|
+
const clientIp = req.socket.remoteAddress || 'unknown';
|
|
33
|
+
const url = req.url || '/';
|
|
34
|
+
// Security Headers
|
|
35
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
36
|
+
res.setHeader('X-Frame-Options', 'DENY');
|
|
37
|
+
res.setHeader('Referrer-Policy', 'no-referrer');
|
|
38
|
+
res.setHeader('Content-Security-Policy', "default-src 'none'");
|
|
39
|
+
// Localhost validation if binding to loopback
|
|
40
|
+
if (this.host === '127.0.0.1' || this.host === 'localhost') {
|
|
41
|
+
if (!validateHost(req, res) || !validateOrigin(req, res)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Rate Limiting Check
|
|
46
|
+
try {
|
|
47
|
+
this.rateLimiter.check(clientIp);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
if (err instanceof RateLimitExceededError) {
|
|
51
|
+
res.writeHead(429, {
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
'Retry-After': String(err.retryAfterSeconds),
|
|
54
|
+
});
|
|
55
|
+
res.end(JSON.stringify({ error: err.message, retryAfter: err.retryAfterSeconds }));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Authentication Check for remote endpoints
|
|
60
|
+
if (this.apiKey) {
|
|
61
|
+
const authHeader = req.headers['authorization'];
|
|
62
|
+
const apiKeyHeader = req.headers['x-api-key'];
|
|
63
|
+
const token = apiKeyHeader ||
|
|
64
|
+
(authHeader && authHeader.startsWith('Bearer ') ? authHeader.substring(7) : null);
|
|
65
|
+
if (token !== this.apiKey && url !== '/health' && url !== '/ready') {
|
|
66
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
67
|
+
res.end(JSON.stringify({ error: 'Unauthorized: Invalid or missing API key' }));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// 1. Health endpoint (Liveness)
|
|
72
|
+
if (url === '/health' && req.method === 'GET') {
|
|
73
|
+
try {
|
|
74
|
+
const health = await this.healthService.getHealth();
|
|
75
|
+
res.writeHead(health.status === 'healthy' ? 200 : 503, {
|
|
76
|
+
'Content-Type': 'application/json',
|
|
77
|
+
});
|
|
78
|
+
res.end(JSON.stringify(health, null, 2));
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
82
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
83
|
+
res.end(JSON.stringify({ status: 'unhealthy', error: msg }));
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// 2. Readiness endpoint
|
|
88
|
+
if (url === '/ready' && req.method === 'GET') {
|
|
89
|
+
try {
|
|
90
|
+
const readiness = this.healthService.getReadiness();
|
|
91
|
+
res.writeHead(readiness.status === 'ready' ? 200 : 503, {
|
|
92
|
+
'Content-Type': 'application/json',
|
|
93
|
+
});
|
|
94
|
+
res.end(JSON.stringify(readiness, null, 2));
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
98
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
99
|
+
res.end(JSON.stringify({ status: 'not_ready', error: msg }));
|
|
100
|
+
}
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// 3. Metrics endpoint
|
|
104
|
+
if (url === '/metrics' && req.method === 'GET') {
|
|
105
|
+
const snapshot = globalMetrics.getSnapshot();
|
|
106
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
107
|
+
res.end(JSON.stringify(snapshot, null, 2));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// 4. MCP Streamable HTTP endpoint (/mcp or root)
|
|
111
|
+
if (url.startsWith('/mcp') || url === '/') {
|
|
112
|
+
try {
|
|
113
|
+
await this.transport.handleRequest(req, res);
|
|
114
|
+
const duration = Math.round(performance.now() - startTime);
|
|
115
|
+
logger.debug('Handled MCP Streamable HTTP request', { url, durationMs: duration });
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
119
|
+
logger.error('Error handling MCP Streamable HTTP request', { error: msg });
|
|
120
|
+
if (!res.headersSent) {
|
|
121
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
122
|
+
res.end(JSON.stringify({ error: 'Internal server error processing MCP request' }));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// 404 for other paths
|
|
128
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
129
|
+
res.end(JSON.stringify({ error: `Not found: ${url}` }));
|
|
130
|
+
});
|
|
131
|
+
return new Promise((resolve) => {
|
|
132
|
+
this.httpServer.listen(this.port, this.host, () => {
|
|
133
|
+
logger.info(`Contradiction MCP HTTP Server listening at http://${this.host}:${this.port}/mcp`, {
|
|
134
|
+
port: this.port,
|
|
135
|
+
host: this.host,
|
|
136
|
+
authRequired: Boolean(this.apiKey),
|
|
137
|
+
});
|
|
138
|
+
resolve();
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
getPort() {
|
|
143
|
+
const address = this.httpServer?.address();
|
|
144
|
+
if (address && typeof address === 'object') {
|
|
145
|
+
return address.port;
|
|
146
|
+
}
|
|
147
|
+
return this.port;
|
|
148
|
+
}
|
|
149
|
+
async stop() {
|
|
150
|
+
if (this.httpServer) {
|
|
151
|
+
if (typeof this.httpServer.closeAllConnections === 'function') {
|
|
152
|
+
this.httpServer.closeAllConnections();
|
|
153
|
+
}
|
|
154
|
+
await new Promise((resolve) => {
|
|
155
|
+
this.httpServer.close(() => resolve());
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (this.transport) {
|
|
159
|
+
await this.transport.close();
|
|
160
|
+
}
|
|
161
|
+
logger.info('Contradiction MCP HTTP Server stopped');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=httpServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpServer.js","sourceRoot":"","sources":["../src/httpServer.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';
|
|
2
|
+
import { config } from './config/env.js';
|
|
3
|
+
import { logger } from './utils/logger.js';
|
|
4
|
+
import { DatabaseManager } from './storage/database.js';
|
|
5
|
+
import { HealthService } from './services/healthService.js';
|
|
6
|
+
import { AnalysisService } from './services/analysisService.js';
|
|
7
|
+
import { DiscoveryService } from './discovery/discoveryService.js';
|
|
8
|
+
import { ConnectorRegistry } from './connectors/connectorRegistry.js';
|
|
9
|
+
import { GitHubClient } from './connectors/github/githubClient.js';
|
|
10
|
+
import { GitHubConnector } from './connectors/github/githubConnector.js';
|
|
11
|
+
import { DocumentConnector } from './connectors/document/documentConnector.js';
|
|
12
|
+
import { WebsiteConnector } from './connectors/website/websiteConnector.js';
|
|
13
|
+
import { SyncService } from './connectors/syncService.js';
|
|
14
|
+
import { createMcpServer } from './server.js';
|
|
15
|
+
async function main() {
|
|
16
|
+
logger.info('Starting Contradiction MCP server...', {
|
|
17
|
+
env: config.NODE_ENV,
|
|
18
|
+
server: config.SERVER_NAME,
|
|
19
|
+
version: config.SERVER_VERSION,
|
|
20
|
+
});
|
|
21
|
+
const dbManager = new DatabaseManager(config.DATABASE_PATH);
|
|
22
|
+
try {
|
|
23
|
+
dbManager.initialize();
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
logger.error('Failed to start server due to database initialization failure', {
|
|
27
|
+
error: error instanceof Error ? error.message : String(error),
|
|
28
|
+
});
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const healthService = new HealthService(dbManager, config);
|
|
32
|
+
const analysisService = new AnalysisService(dbManager);
|
|
33
|
+
const discoveryService = new DiscoveryService(dbManager);
|
|
34
|
+
// Initialize connector registry and register connectors
|
|
35
|
+
const connectorRegistry = new ConnectorRegistry();
|
|
36
|
+
const githubClient = new GitHubClient({ token: config.GITHUB_TOKEN });
|
|
37
|
+
const githubConnector = new GitHubConnector(githubClient);
|
|
38
|
+
connectorRegistry.register(githubConnector);
|
|
39
|
+
const documentConnector = new DocumentConnector();
|
|
40
|
+
connectorRegistry.register(documentConnector);
|
|
41
|
+
const websiteConnector = new WebsiteConnector();
|
|
42
|
+
connectorRegistry.register(websiteConnector);
|
|
43
|
+
const syncService = new SyncService(dbManager, connectorRegistry, discoveryService);
|
|
44
|
+
const server = createMcpServer({
|
|
45
|
+
healthService,
|
|
46
|
+
analysisService,
|
|
47
|
+
discoveryService,
|
|
48
|
+
dbManager,
|
|
49
|
+
connectorRegistry,
|
|
50
|
+
syncService,
|
|
51
|
+
name: config.SERVER_NAME,
|
|
52
|
+
version: config.SERVER_VERSION,
|
|
53
|
+
});
|
|
54
|
+
let httpServer = null;
|
|
55
|
+
const shutdown = async (signal) => {
|
|
56
|
+
logger.info(`Received ${signal}, shutting down gracefully...`);
|
|
57
|
+
try {
|
|
58
|
+
if (httpServer) {
|
|
59
|
+
await httpServer.stop();
|
|
60
|
+
}
|
|
61
|
+
await server.close();
|
|
62
|
+
dbManager.close();
|
|
63
|
+
logger.info('Contradiction MCP server stopped cleanly');
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
logger.error('Error during graceful shutdown', { error: String(err) });
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
process.on('SIGINT', () => void shutdown('SIGINT'));
|
|
72
|
+
process.on('SIGTERM', () => void shutdown('SIGTERM'));
|
|
73
|
+
if (config.MCP_TRANSPORT === 'http') {
|
|
74
|
+
const { McpHttpServer } = await import('./httpServer.js');
|
|
75
|
+
httpServer = new McpHttpServer({
|
|
76
|
+
server,
|
|
77
|
+
healthService,
|
|
78
|
+
port: config.HTTP_PORT,
|
|
79
|
+
host: config.HTTP_HOST,
|
|
80
|
+
apiKey: config.API_KEY,
|
|
81
|
+
});
|
|
82
|
+
await httpServer.start();
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const transport = new StdioServerTransport();
|
|
86
|
+
await server.connect(transport);
|
|
87
|
+
logger.info('Contradiction MCP server running and listening via stdio transport');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
main().catch((error) => {
|
|
91
|
+
logger.error('Fatal error in server process', { error: String(error) });
|
|
92
|
+
process.exit(1);
|
|
93
|
+
});
|
|
94
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,IAAI,CAAC,sCAAsC,EAAE;QAClD,GAAG,EAAE,MAAM,CAAC,QAAQ;QACpB,MAAM,EAAE,MAAM,CAAC,WAAW;QAC1B,OAAO,EAAE,MAAM,CAAC,cAAc;KAC/B,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,SAAS,CAAC,UAAU,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,+DAA+D,EAAE;YAC5E,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC3D,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC,SAAS,CAAC,CAAC;IACvD,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAEzD,wDAAwD;IACxD,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAClD,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IACtE,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC,YAAY,CAAC,CAAC;IAC1D,iBAAiB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAE5C,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAClD,iBAAiB,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IAE9C,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,EAAE,CAAC;IAChD,iBAAiB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAE7C,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;IAEpF,MAAM,MAAM,GAAG,eAAe,CAAC;QAC7B,aAAa;QACb,eAAe;QACf,gBAAgB;QAChB,SAAS;QACT,iBAAiB;QACjB,WAAW;QACX,IAAI,EAAE,MAAM,CAAC,WAAW;QACxB,OAAO,EAAE,MAAM,CAAC,cAAc;KAC/B,CAAC,CAAC;IAEH,IAAI,UAAU,GAAmD,IAAI,CAAC;IAEtE,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QACxC,MAAM,CAAC,IAAI,CAAC,YAAY,MAAM,+BAA+B,CAAC,CAAC;QAC/D,IAAI,CAAC;YACH,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;YAC1B,CAAC;YACD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAEtD,IAAI,MAAM,CAAC,aAAa,KAAK,MAAM,EAAE,CAAC;QACpC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAC1D,UAAU,GAAG,IAAI,aAAa,CAAC;YAC7B,MAAM;YACN,aAAa;YACb,IAAI,EAAE,MAAM,CAAC,SAAS;YACtB,IAAI,EAAE,MAAM,CAAC,SAAS;YACtB,MAAM,EAAE,MAAM,CAAC,OAAO;SACvB,CAAC,CAAC;QACH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;IACpF,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Claim } from '../domain/entities/claim.js';
|
|
2
|
+
import { Source } from '../domain/entities/source.js';
|
|
3
|
+
export interface AuthorityScoreBreakdown {
|
|
4
|
+
roleScore: number;
|
|
5
|
+
trustScore: number;
|
|
6
|
+
locationScore: number;
|
|
7
|
+
directnessScore: number;
|
|
8
|
+
}
|
|
9
|
+
export interface AuthorityScoreResult {
|
|
10
|
+
score: number;
|
|
11
|
+
breakdown: AuthorityScoreBreakdown;
|
|
12
|
+
reasoning: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare class AuthorityScorer {
|
|
15
|
+
/**
|
|
16
|
+
* Deterministically calculates an authority score between 0.0 and 1.0 for a claim
|
|
17
|
+
* based on source role, source trust, document location/type, and directness of evidence.
|
|
18
|
+
*/
|
|
19
|
+
scoreAuthority(claim: Claim, source?: Source | null): AuthorityScoreResult;
|
|
20
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
export class AuthorityScorer {
|
|
2
|
+
/**
|
|
3
|
+
* Deterministically calculates an authority score between 0.0 and 1.0 for a claim
|
|
4
|
+
* based on source role, source trust, document location/type, and directness of evidence.
|
|
5
|
+
*/
|
|
6
|
+
scoreAuthority(claim, source) {
|
|
7
|
+
const reasoning = [];
|
|
8
|
+
// 1. Source Role Score (weight: 0.40)
|
|
9
|
+
let roleScore;
|
|
10
|
+
const role = (claim.sourceRole || 'unknown').toLowerCase();
|
|
11
|
+
switch (role) {
|
|
12
|
+
case 'authoritative':
|
|
13
|
+
roleScore = 1.0;
|
|
14
|
+
reasoning.push('Explicit authoritative role designation (score: 1.00)');
|
|
15
|
+
break;
|
|
16
|
+
case 'deployment':
|
|
17
|
+
roleScore = 0.95;
|
|
18
|
+
reasoning.push('Deployment specification role provides primary operational truth (score: 0.95)');
|
|
19
|
+
break;
|
|
20
|
+
case 'configuration':
|
|
21
|
+
roleScore = 0.9;
|
|
22
|
+
reasoning.push('Configuration source role indicates runtime authority (score: 0.90)');
|
|
23
|
+
break;
|
|
24
|
+
case 'documentation':
|
|
25
|
+
roleScore = 0.55;
|
|
26
|
+
reasoning.push('Documentation source role is secondary to operational configuration (score: 0.55)');
|
|
27
|
+
break;
|
|
28
|
+
case 'generated':
|
|
29
|
+
roleScore = 0.45;
|
|
30
|
+
reasoning.push('Generated or synthetic artifact (score: 0.45)');
|
|
31
|
+
break;
|
|
32
|
+
case 'example':
|
|
33
|
+
roleScore = 0.25;
|
|
34
|
+
reasoning.push('Example or template code has low production authority (score: 0.25)');
|
|
35
|
+
break;
|
|
36
|
+
case 'historical':
|
|
37
|
+
roleScore = 0.15;
|
|
38
|
+
reasoning.push('Historical marker significantly degrades authority (score: 0.15)');
|
|
39
|
+
break;
|
|
40
|
+
default:
|
|
41
|
+
roleScore = 0.5;
|
|
42
|
+
reasoning.push('Default/unknown role score applied (score: 0.50)');
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
// 2. Source Trust Score (weight: 0.25)
|
|
46
|
+
const trustScore = source?.trustScore ?? 1.0;
|
|
47
|
+
reasoning.push(`Source '${source?.name || 'unknown'}' trust score: ${trustScore.toFixed(2)}`);
|
|
48
|
+
// 3. Document Location / Type Heuristic (weight: 0.20)
|
|
49
|
+
let locationScore;
|
|
50
|
+
const metadata = claim.metadata || {};
|
|
51
|
+
const filePath = typeof metadata.filePath === 'string' ? metadata.filePath.toLowerCase() : '';
|
|
52
|
+
const uri = typeof metadata.uri === 'string' ? metadata.uri.toLowerCase() : '';
|
|
53
|
+
if (filePath.endsWith('dockerfile') || filePath.includes('.github/workflows')) {
|
|
54
|
+
locationScore = 0.95;
|
|
55
|
+
reasoning.push(`Location '${filePath}' is a deployment/CI pipeline spec (score: 0.95)`);
|
|
56
|
+
}
|
|
57
|
+
else if (filePath.endsWith('package.json') ||
|
|
58
|
+
filePath.endsWith('pom.xml') ||
|
|
59
|
+
filePath.endsWith('cargo.toml')) {
|
|
60
|
+
locationScore = 0.9;
|
|
61
|
+
reasoning.push(`Location '${filePath}' is a project manifest specification (score: 0.90)`);
|
|
62
|
+
}
|
|
63
|
+
else if (filePath.endsWith('.env') ||
|
|
64
|
+
filePath.endsWith('.yaml') ||
|
|
65
|
+
filePath.endsWith('.json')) {
|
|
66
|
+
locationScore = 0.85;
|
|
67
|
+
reasoning.push(`Location '${filePath}' is structured configuration (score: 0.85)`);
|
|
68
|
+
}
|
|
69
|
+
else if (filePath.endsWith('.md') || filePath.endsWith('.txt') || uri.includes('/docs/')) {
|
|
70
|
+
locationScore = 0.5;
|
|
71
|
+
reasoning.push(`Location '${filePath || uri}' is documentation text (score: 0.50)`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
locationScore = 0.6;
|
|
75
|
+
reasoning.push('Generic file location score (score: 0.60)');
|
|
76
|
+
}
|
|
77
|
+
// 4. Evidence Directness Score (weight: 0.15)
|
|
78
|
+
let directnessScore = 0.5;
|
|
79
|
+
if (metadata.line !== undefined ||
|
|
80
|
+
(metadata.startLine !== undefined && metadata.endLine !== undefined)) {
|
|
81
|
+
directnessScore += 0.25;
|
|
82
|
+
reasoning.push('Exact line provenance provides direct verifiable evidence');
|
|
83
|
+
}
|
|
84
|
+
if (typeof metadata.snippet === 'string' && metadata.snippet.trim().length > 0) {
|
|
85
|
+
directnessScore += 0.25;
|
|
86
|
+
reasoning.push('Verbatim snippet available');
|
|
87
|
+
}
|
|
88
|
+
directnessScore = Math.min(1.0, directnessScore);
|
|
89
|
+
// Weighted composite authority score
|
|
90
|
+
const score = Number((roleScore * 0.4 + trustScore * 0.25 + locationScore * 0.2 + directnessScore * 0.15).toFixed(4));
|
|
91
|
+
return {
|
|
92
|
+
score,
|
|
93
|
+
breakdown: {
|
|
94
|
+
roleScore,
|
|
95
|
+
trustScore,
|
|
96
|
+
locationScore,
|
|
97
|
+
directnessScore,
|
|
98
|
+
},
|
|
99
|
+
reasoning,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=authorityScorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorityScorer.js","sourceRoot":"","sources":["../../src/intelligence/authorityScorer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface EntityMatchResult {
|
|
2
|
+
isMatch: boolean;
|
|
3
|
+
confidence: number;
|
|
4
|
+
matchType: 'EXACT' | 'NORMALIZED' | 'ALIAS' | 'SUFFIX_PREFIX' | 'URL_HOST' | 'NONE';
|
|
5
|
+
reason: string;
|
|
6
|
+
isAmbiguous: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface CandidateMatch {
|
|
9
|
+
candidate: string;
|
|
10
|
+
confidence: number;
|
|
11
|
+
matchType: string;
|
|
12
|
+
}
|
|
13
|
+
export interface EntityResolverOptions {
|
|
14
|
+
customAliases?: Record<string, string[]>;
|
|
15
|
+
minConfidenceThreshold?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class EntityResolver {
|
|
18
|
+
private readonly defaultAliases;
|
|
19
|
+
constructor();
|
|
20
|
+
private registerDefaultAliases;
|
|
21
|
+
/**
|
|
22
|
+
* Canonicalizes an entity name by stripping delimiters, common redundant words, and casing.
|
|
23
|
+
*/
|
|
24
|
+
normalize(raw: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Compares two entity references across sources.
|
|
27
|
+
*/
|
|
28
|
+
resolveEntityMatch(entityA: string, entityB: string, options?: EntityResolverOptions): EntityMatchResult;
|
|
29
|
+
/**
|
|
30
|
+
* Evaluates query against multiple candidate entities, sorting by confidence.
|
|
31
|
+
*/
|
|
32
|
+
findMatches(query: string, candidates: string[], options?: EntityResolverOptions): CandidateMatch[];
|
|
33
|
+
}
|