@sandrobuilds/tracerney 0.9.6
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/README.md +702 -0
- package/dist/application/ShieldApplicationService.d.ts +94 -0
- package/dist/application/ShieldApplicationService.d.ts.map +1 -0
- package/dist/application/ShieldApplicationService.js +223 -0
- package/dist/application/ShieldApplicationService.js.map +1 -0
- package/dist/application/ShieldBlockError.d.ts +10 -0
- package/dist/application/ShieldBlockError.d.ts.map +1 -0
- package/dist/application/ShieldBlockError.js +13 -0
- package/dist/application/ShieldBlockError.js.map +1 -0
- package/dist/application/index.d.ts +9 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/index.js +8 -0
- package/dist/application/index.js.map +1 -0
- package/dist/application/ports/ILLMProvider.d.ts +71 -0
- package/dist/application/ports/ILLMProvider.d.ts.map +1 -0
- package/dist/application/ports/ILLMProvider.js +15 -0
- package/dist/application/ports/ILLMProvider.js.map +1 -0
- package/dist/application/ports/IPatternRepository.d.ts +20 -0
- package/dist/application/ports/IPatternRepository.d.ts.map +1 -0
- package/dist/application/ports/IPatternRepository.js +7 -0
- package/dist/application/ports/IPatternRepository.js.map +1 -0
- package/dist/application/ports/ISentinel.d.ts +22 -0
- package/dist/application/ports/ISentinel.d.ts.map +1 -0
- package/dist/application/ports/ISentinel.js +8 -0
- package/dist/application/ports/ISentinel.js.map +1 -0
- package/dist/application/ports/ITelemetrySink.d.ts +35 -0
- package/dist/application/ports/ITelemetrySink.d.ts.map +1 -0
- package/dist/application/ports/ITelemetrySink.js +7 -0
- package/dist/application/ports/ITelemetrySink.js.map +1 -0
- package/dist/application/ports/index.d.ts +10 -0
- package/dist/application/ports/index.d.ts.map +1 -0
- package/dist/application/ports/index.js +7 -0
- package/dist/application/ports/index.js.map +1 -0
- package/dist/application/utils/index.d.ts +6 -0
- package/dist/application/utils/index.d.ts.map +1 -0
- package/dist/application/utils/index.js +6 -0
- package/dist/application/utils/index.js.map +1 -0
- package/dist/application/utils/jitter.d.ts +10 -0
- package/dist/application/utils/jitter.d.ts.map +1 -0
- package/dist/application/utils/jitter.js +13 -0
- package/dist/application/utils/jitter.js.map +1 -0
- package/dist/application/utils/normalizePrompt.d.ts +18 -0
- package/dist/application/utils/normalizePrompt.d.ts.map +1 -0
- package/dist/application/utils/normalizePrompt.js +36 -0
- package/dist/application/utils/normalizePrompt.js.map +1 -0
- package/dist/domain/detection/InjectionThreat.d.ts +19 -0
- package/dist/domain/detection/InjectionThreat.d.ts.map +1 -0
- package/dist/domain/detection/InjectionThreat.js +18 -0
- package/dist/domain/detection/InjectionThreat.js.map +1 -0
- package/dist/domain/detection/PatternMatcher.d.ts +36 -0
- package/dist/domain/detection/PatternMatcher.d.ts.map +1 -0
- package/dist/domain/detection/PatternMatcher.js +65 -0
- package/dist/domain/detection/PatternMatcher.js.map +1 -0
- package/dist/domain/detection/VanguardPattern.d.ts +19 -0
- package/dist/domain/detection/VanguardPattern.d.ts.map +1 -0
- package/dist/domain/detection/VanguardPattern.js +21 -0
- package/dist/domain/detection/VanguardPattern.js.map +1 -0
- package/dist/domain/detection/index.d.ts +11 -0
- package/dist/domain/detection/index.d.ts.map +1 -0
- package/dist/domain/detection/index.js +8 -0
- package/dist/domain/detection/index.js.map +1 -0
- package/dist/domain/events/SecurityEvent.d.ts +30 -0
- package/dist/domain/events/SecurityEvent.d.ts.map +1 -0
- package/dist/domain/events/SecurityEvent.js +21 -0
- package/dist/domain/events/SecurityEvent.js.map +1 -0
- package/dist/domain/events/SecurityEventType.d.ts +13 -0
- package/dist/domain/events/SecurityEventType.d.ts.map +1 -0
- package/dist/domain/events/SecurityEventType.js +15 -0
- package/dist/domain/events/SecurityEventType.js.map +1 -0
- package/dist/domain/events/ThreatSeverity.d.ts +13 -0
- package/dist/domain/events/ThreatSeverity.d.ts.map +1 -0
- package/dist/domain/events/ThreatSeverity.js +15 -0
- package/dist/domain/events/ThreatSeverity.js.map +1 -0
- package/dist/domain/events/index.d.ts +11 -0
- package/dist/domain/events/index.d.ts.map +1 -0
- package/dist/domain/events/index.js +8 -0
- package/dist/domain/events/index.js.map +1 -0
- package/dist/domain/guard/ToolGuard.d.ts +35 -0
- package/dist/domain/guard/ToolGuard.d.ts.map +1 -0
- package/dist/domain/guard/ToolGuard.js +49 -0
- package/dist/domain/guard/ToolGuard.js.map +1 -0
- package/dist/domain/guard/ToolPolicy.d.ts +16 -0
- package/dist/domain/guard/ToolPolicy.d.ts.map +1 -0
- package/dist/domain/guard/ToolPolicy.js +19 -0
- package/dist/domain/guard/ToolPolicy.js.map +1 -0
- package/dist/domain/guard/ToolViolation.d.ts +14 -0
- package/dist/domain/guard/ToolViolation.d.ts.map +1 -0
- package/dist/domain/guard/ToolViolation.js +15 -0
- package/dist/domain/guard/ToolViolation.js.map +1 -0
- package/dist/domain/guard/index.d.ts +11 -0
- package/dist/domain/guard/index.d.ts.map +1 -0
- package/dist/domain/guard/index.js +8 -0
- package/dist/domain/guard/index.js.map +1 -0
- package/dist/index.d.ts +168 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +173 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/llm/OpenRouterProvider.d.ts +32 -0
- package/dist/infrastructure/llm/OpenRouterProvider.d.ts.map +1 -0
- package/dist/infrastructure/llm/OpenRouterProvider.js +119 -0
- package/dist/infrastructure/llm/OpenRouterProvider.js.map +1 -0
- package/dist/infrastructure/llm/index.d.ts +7 -0
- package/dist/infrastructure/llm/index.d.ts.map +1 -0
- package/dist/infrastructure/llm/index.js +6 -0
- package/dist/infrastructure/llm/index.js.map +1 -0
- package/dist/infrastructure/patterns/BundledPatternRepository.d.ts +16 -0
- package/dist/infrastructure/patterns/BundledPatternRepository.d.ts.map +1 -0
- package/dist/infrastructure/patterns/BundledPatternRepository.js +19 -0
- package/dist/infrastructure/patterns/BundledPatternRepository.js.map +1 -0
- package/dist/infrastructure/patterns/RemotePatternRepository.d.ts +77 -0
- package/dist/infrastructure/patterns/RemotePatternRepository.d.ts.map +1 -0
- package/dist/infrastructure/patterns/RemotePatternRepository.js +176 -0
- package/dist/infrastructure/patterns/RemotePatternRepository.js.map +1 -0
- package/dist/infrastructure/patterns/bundled-patterns.d.ts +9 -0
- package/dist/infrastructure/patterns/bundled-patterns.d.ts.map +1 -0
- package/dist/infrastructure/patterns/bundled-patterns.js +2082 -0
- package/dist/infrastructure/patterns/bundled-patterns.js.map +1 -0
- package/dist/infrastructure/patterns/index.d.ts +9 -0
- package/dist/infrastructure/patterns/index.d.ts.map +1 -0
- package/dist/infrastructure/patterns/index.js +8 -0
- package/dist/infrastructure/patterns/index.js.map +1 -0
- package/dist/infrastructure/sentinel/LLMSentinel.d.ts +48 -0
- package/dist/infrastructure/sentinel/LLMSentinel.d.ts.map +1 -0
- package/dist/infrastructure/sentinel/LLMSentinel.js +142 -0
- package/dist/infrastructure/sentinel/LLMSentinel.js.map +1 -0
- package/dist/infrastructure/telemetry/HttpShadowLogSink.d.ts +30 -0
- package/dist/infrastructure/telemetry/HttpShadowLogSink.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/HttpShadowLogSink.js +40 -0
- package/dist/infrastructure/telemetry/HttpShadowLogSink.js.map +1 -0
- package/dist/infrastructure/telemetry/HttpSignalSink.d.ts +51 -0
- package/dist/infrastructure/telemetry/HttpSignalSink.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/HttpSignalSink.js +134 -0
- package/dist/infrastructure/telemetry/HttpSignalSink.js.map +1 -0
- package/dist/infrastructure/telemetry/index.d.ts +9 -0
- package/dist/infrastructure/telemetry/index.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/index.js +7 -0
- package/dist/infrastructure/telemetry/index.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolGuard.js","sourceRoot":"","sources":["../../../src/domain/guard/ToolGuard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAc,aAAa,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAiB,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAWrE,MAAM,OAAO,SAAS;IACpB,YAAoB,MAAkB;QAAlB,WAAM,GAAN,MAAM,CAAY;QACpC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CACN,SAA0C,EAC1C,SAAiB;QAEjB,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,CAAC,8BAA8B;QAC7C,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;YAExC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;gBAC1C,OAAO,mBAAmB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC,CAAC,wBAAwB;IACvC,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,MAAkB;QAC7B,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,eAAe;QACb,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC9C,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Policy
|
|
3
|
+
* Domain value object: the allow-list rule set
|
|
4
|
+
*/
|
|
5
|
+
export interface ToolPolicy {
|
|
6
|
+
readonly allowedTools: ReadonlySet<string>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Factory to create a ToolPolicy from an array
|
|
10
|
+
*/
|
|
11
|
+
export declare function createToolPolicy(allowedTools: readonly string[]): ToolPolicy;
|
|
12
|
+
/**
|
|
13
|
+
* Check if a tool is allowed by the policy
|
|
14
|
+
*/
|
|
15
|
+
export declare function isToolAllowed(policy: ToolPolicy, toolName: string): boolean;
|
|
16
|
+
//# sourceMappingURL=ToolPolicy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolPolicy.d.ts","sourceRoot":"","sources":["../../../src/domain/guard/ToolPolicy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC5C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAI5E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE3E"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Policy
|
|
3
|
+
* Domain value object: the allow-list rule set
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Factory to create a ToolPolicy from an array
|
|
7
|
+
*/
|
|
8
|
+
export function createToolPolicy(allowedTools) {
|
|
9
|
+
return {
|
|
10
|
+
allowedTools: new Set(allowedTools),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Check if a tool is allowed by the policy
|
|
15
|
+
*/
|
|
16
|
+
export function isToolAllowed(policy, toolName) {
|
|
17
|
+
return policy.allowedTools.has(toolName);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ToolPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolPolicy.js","sourceRoot":"","sources":["../../../src/domain/guard/ToolPolicy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,YAA+B;IAC9D,OAAO;QACL,YAAY,EAAE,IAAI,GAAG,CAAC,YAAY,CAAC;KACpC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,MAAkB,EAAE,QAAgB;IAChE,OAAO,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Violation
|
|
3
|
+
* Domain value object: result of a policy breach
|
|
4
|
+
*/
|
|
5
|
+
export interface ToolViolation {
|
|
6
|
+
readonly toolName: string;
|
|
7
|
+
readonly requestId: string;
|
|
8
|
+
readonly detectedAt: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Factory to create a ToolViolation
|
|
12
|
+
*/
|
|
13
|
+
export declare function createToolViolation(toolName: string, requestId: string, detectedAt?: number): ToolViolation;
|
|
14
|
+
//# sourceMappingURL=ToolViolation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolViolation.d.ts","sourceRoot":"","sources":["../../../src/domain/guard/ToolViolation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB,aAAa,CAMf"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Violation
|
|
3
|
+
* Domain value object: result of a policy breach
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Factory to create a ToolViolation
|
|
7
|
+
*/
|
|
8
|
+
export function createToolViolation(toolName, requestId, detectedAt) {
|
|
9
|
+
return {
|
|
10
|
+
toolName,
|
|
11
|
+
requestId,
|
|
12
|
+
detectedAt: detectedAt ?? Date.now(),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=ToolViolation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolViolation.js","sourceRoot":"","sources":["../../../src/domain/guard/ToolViolation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,SAAiB,EACjB,UAAmB;IAEnB,OAAO;QACL,QAAQ;QACR,SAAS;QACT,UAAU,EAAE,UAAU,IAAI,IAAI,CAAC,GAAG,EAAE;KACrC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guard Bounded Context
|
|
3
|
+
* Barrel export
|
|
4
|
+
*/
|
|
5
|
+
export { createToolPolicy, isToolAllowed } from "./ToolPolicy";
|
|
6
|
+
export type { ToolPolicy } from "./ToolPolicy";
|
|
7
|
+
export { createToolViolation } from "./ToolViolation";
|
|
8
|
+
export type { ToolViolation } from "./ToolViolation";
|
|
9
|
+
export { ToolGuard } from "./ToolGuard";
|
|
10
|
+
export type { ToolCall } from "./ToolGuard";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/guard/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/domain/guard/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracerny
|
|
3
|
+
* Transparent Proxy Runtime Sentinel for Prompt Injection Defense
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { Tracerny } from 'tracerney';
|
|
8
|
+
*
|
|
9
|
+
* const shield = new Tracerny({
|
|
10
|
+
* allowedTools: ['search', 'calculator'],
|
|
11
|
+
* apiEndpoint: 'https://api.myapp.com/v1/signal',
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* const response = await shield.wrap(() =>
|
|
15
|
+
* openai.chat.completions.create({...})
|
|
16
|
+
* );
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import { type WrapOptions, type ServiceStatus } from "./application";
|
|
20
|
+
import { ShieldBlockError } from "./application/ShieldBlockError";
|
|
21
|
+
import { type LLMResponse } from "./application/ports/ILLMProvider";
|
|
22
|
+
/**
|
|
23
|
+
* Public configuration for Tracerny
|
|
24
|
+
*/
|
|
25
|
+
export interface TracernyOptions {
|
|
26
|
+
/**
|
|
27
|
+
* List of tool names the LLM is allowed to call
|
|
28
|
+
*/
|
|
29
|
+
allowedTools?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* Base URL for your Tracerny backend (RECOMMENDED)
|
|
32
|
+
* Automatically constructs all required endpoints:
|
|
33
|
+
* - Signal endpoint: {baseUrl}/api/v1/signal
|
|
34
|
+
* - Verification endpoint: {baseUrl}/api/v1/verify-prompt
|
|
35
|
+
* - Shadow log endpoint: {baseUrl}/api/v1/shadow-log
|
|
36
|
+
* - Definitions endpoint: {baseUrl}/api/v1/definitions
|
|
37
|
+
*
|
|
38
|
+
* Example: https://myapp.com or http://localhost:3000
|
|
39
|
+
*
|
|
40
|
+
* If provided, individual endpoint URLs below are ignored.
|
|
41
|
+
*/
|
|
42
|
+
baseUrl?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Your backend's Signal Sink endpoint for receiving security events
|
|
45
|
+
* Only needed if NOT using baseUrl
|
|
46
|
+
* Example: https://myapp.com/api/v1/signal
|
|
47
|
+
*/
|
|
48
|
+
apiEndpoint?: string;
|
|
49
|
+
/**
|
|
50
|
+
* API key for Signal Sink (optional, sent in Authorization header)
|
|
51
|
+
*/
|
|
52
|
+
apiKey?: string;
|
|
53
|
+
/**
|
|
54
|
+
* URL to fetch pattern manifest from (for zero-day updates)
|
|
55
|
+
* If not provided, bundled patterns are used
|
|
56
|
+
*/
|
|
57
|
+
manifestUrl?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Enable telemetry reporting (default: true)
|
|
60
|
+
*/
|
|
61
|
+
enableTelemetry?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Local path to cache manifest (useful in serverless, e.g., /tmp)
|
|
64
|
+
*/
|
|
65
|
+
localManifestPath?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Layer 2: Backend endpoint for LLM verification
|
|
68
|
+
* SDK sends suspicious prompts here (backend calls OpenRouter internally)
|
|
69
|
+
* Example: https://myapp.com/api/v1/verify-prompt
|
|
70
|
+
*/
|
|
71
|
+
sentinelEndpoint?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Endpoint for shadow log (records of potential attacks)
|
|
74
|
+
* Example: https://myapp.com/api/v1/shadow-log
|
|
75
|
+
*/
|
|
76
|
+
shadowLogEndpoint?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Enable Layer 2 LLM Sentinel (default: true if sentinelEndpoint provided)
|
|
79
|
+
*/
|
|
80
|
+
sentinelEnabled?: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Tracerny Facade
|
|
84
|
+
* Main entry point for the SDK
|
|
85
|
+
* Wires all dependencies: domain + application + infrastructure
|
|
86
|
+
*/
|
|
87
|
+
export declare class Tracerny {
|
|
88
|
+
private service;
|
|
89
|
+
/**
|
|
90
|
+
* Constructor: wires the full dependency graph
|
|
91
|
+
*/
|
|
92
|
+
constructor(options?: TracernyOptions);
|
|
93
|
+
/**
|
|
94
|
+
* Resolves baseUrl into individual endpoint URLs
|
|
95
|
+
* baseUrl takes precedence over individual endpoint options
|
|
96
|
+
*/
|
|
97
|
+
private resolveEndpoints;
|
|
98
|
+
/**
|
|
99
|
+
* Main wrapper for LLM calls
|
|
100
|
+
*
|
|
101
|
+
* @param llmCall - Function that executes the LLM call
|
|
102
|
+
* @param options - Optional: prompt for pre-LLM scanning, request context
|
|
103
|
+
*
|
|
104
|
+
* @throws ShieldBlockError if an injection or unauthorized tool is detected
|
|
105
|
+
* @throws Other errors from the LLM provider or network failures
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* // With optional prompt for pre-LLM scanning (fixes Gap 3)
|
|
110
|
+
* const response = await shield.wrap(
|
|
111
|
+
* () => openai.chat.completions.create({...}),
|
|
112
|
+
* { prompt: userInput }
|
|
113
|
+
* );
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
wrap<T extends LLMResponse>(llmCall: () => Promise<T>, options?: WrapOptions): Promise<T>;
|
|
117
|
+
/**
|
|
118
|
+
* Scan a raw prompt for injection attempts (standalone use)
|
|
119
|
+
*
|
|
120
|
+
* @param prompt - The user input to scan
|
|
121
|
+
* @throws ShieldBlockError if injection is detected
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript
|
|
125
|
+
* try {
|
|
126
|
+
* await shield.scanPrompt(userInput);
|
|
127
|
+
* // Safe to proceed
|
|
128
|
+
* } catch (err) {
|
|
129
|
+
* if (err instanceof ShieldBlockError) {
|
|
130
|
+
* // Attack detected
|
|
131
|
+
* }
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
scanPrompt(prompt: string): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Update allowed tools at runtime
|
|
138
|
+
*
|
|
139
|
+
* @param tools - New list of allowed tool names
|
|
140
|
+
*/
|
|
141
|
+
setAllowedTools(tools: string[]): void;
|
|
142
|
+
/**
|
|
143
|
+
* Get Shield status and diagnostics
|
|
144
|
+
*/
|
|
145
|
+
getStatus(): ServiceStatus;
|
|
146
|
+
/**
|
|
147
|
+
* Graceful shutdown: flushes telemetry and releases resources
|
|
148
|
+
* Call this before process exit
|
|
149
|
+
*/
|
|
150
|
+
destroy(): void;
|
|
151
|
+
}
|
|
152
|
+
export { ShieldBlockError };
|
|
153
|
+
export type { WrapOptions, ServiceStatus, LLMResponse };
|
|
154
|
+
export type { VanguardPattern, PatternCategory, InjectionThreat, } from "./domain/detection";
|
|
155
|
+
export type { ToolPolicy, ToolViolation } from "./domain/guard";
|
|
156
|
+
export type { SecurityEvent, SecurityEventMetadata, ThreatSeverity, SecurityEventType, } from "./domain/events";
|
|
157
|
+
export type { ILLMProvider, LLMRequest, LLMMessage, LLMChoice, ToolCall, LLMTool, TokenUsage, ITelemetrySink, IPatternRepository, } from "./application";
|
|
158
|
+
export { BundledPatternRepository, RemotePatternRepository } from "./infrastructure/patterns";
|
|
159
|
+
export type { RemotePatternRepositoryConfig } from "./infrastructure/patterns";
|
|
160
|
+
export { normalizePrompt, normalizePrompts, jitter } from "./application/utils";
|
|
161
|
+
export { HttpSignalSink } from "./infrastructure/telemetry";
|
|
162
|
+
export type { HttpSignalSinkConfig } from "./infrastructure/telemetry";
|
|
163
|
+
export { LLMSentinel } from "./infrastructure/sentinel/LLMSentinel";
|
|
164
|
+
export type { LLMSentinelOptions } from "./infrastructure/sentinel/LLMSentinel";
|
|
165
|
+
export { HttpShadowLogSink } from "./infrastructure/telemetry/HttpShadowLogSink";
|
|
166
|
+
export type { ShadowLogPayload } from "./infrastructure/telemetry/HttpShadowLogSink";
|
|
167
|
+
export { ShieldApplicationService } from "./application/ShieldApplicationService";
|
|
168
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracerny
|
|
3
|
+
* Transparent Proxy Runtime Sentinel for Prompt Injection Defense
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { Tracerny } from 'tracerney';
|
|
8
|
+
*
|
|
9
|
+
* const shield = new Tracerny({
|
|
10
|
+
* allowedTools: ['search', 'calculator'],
|
|
11
|
+
* apiEndpoint: 'https://api.myapp.com/v1/signal',
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* const response = await shield.wrap(() =>
|
|
15
|
+
* openai.chat.completions.create({...})
|
|
16
|
+
* );
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import { ShieldApplicationService } from './application/index.js';
|
|
20
|
+
import { ShieldBlockError } from './application/ShieldBlockError.js';
|
|
21
|
+
import { createToolPolicy } from './domain/guard/ToolPolicy.js';
|
|
22
|
+
import { BundledPatternRepository } from './infrastructure/patterns/BundledPatternRepository.js';
|
|
23
|
+
import { HttpSignalSink } from './infrastructure/telemetry/HttpSignalSink.js';
|
|
24
|
+
// import { HttpShadowLogSink } from './infrastructure/telemetry/HttpShadowLogSink.js'; // Disabled
|
|
25
|
+
import { LLMSentinel } from './infrastructure/sentinel/LLMSentinel.js';
|
|
26
|
+
/**
|
|
27
|
+
* Tracerny Facade
|
|
28
|
+
* Main entry point for the SDK
|
|
29
|
+
* Wires all dependencies: domain + application + infrastructure
|
|
30
|
+
*/
|
|
31
|
+
export class Tracerny {
|
|
32
|
+
/**
|
|
33
|
+
* Constructor: wires the full dependency graph
|
|
34
|
+
*/
|
|
35
|
+
constructor(options = {}) {
|
|
36
|
+
// Step 0: Resolve endpoints from baseUrl if provided
|
|
37
|
+
const resolvedOptions = this.resolveEndpoints(options);
|
|
38
|
+
// Step 1: Build pattern repository
|
|
39
|
+
// Always use bundled patterns (288 forensic patterns)
|
|
40
|
+
// No remote updates - bundled patterns are production-ready
|
|
41
|
+
const patternRepo = new BundledPatternRepository();
|
|
42
|
+
// Step 2: Build telemetry sink
|
|
43
|
+
const telemetrySink = options.enableTelemetry !== false && resolvedOptions.apiEndpoint
|
|
44
|
+
? new HttpSignalSink({
|
|
45
|
+
endpoint: resolvedOptions.apiEndpoint,
|
|
46
|
+
apiKey: resolvedOptions.apiKey,
|
|
47
|
+
})
|
|
48
|
+
: undefined;
|
|
49
|
+
// Step 3: Create tool policy
|
|
50
|
+
const toolPolicy = createToolPolicy(options.allowedTools ?? []);
|
|
51
|
+
// Step 4: Build Layer 2 LLM Sentinel (if enabled)
|
|
52
|
+
let sentinel = undefined;
|
|
53
|
+
if (options.sentinelEnabled !== false && resolvedOptions.sentinelEndpoint) {
|
|
54
|
+
sentinel = new LLMSentinel(resolvedOptions.sentinelEndpoint, resolvedOptions.apiKey);
|
|
55
|
+
}
|
|
56
|
+
// Step 5: Build shadow log sink (if endpoint provided)
|
|
57
|
+
// DISABLED FOR NOW - will re-enable after fixing endpoint
|
|
58
|
+
// let shadowLogSink = undefined;
|
|
59
|
+
// if (resolvedOptions.shadowLogEndpoint) {
|
|
60
|
+
// shadowLogSink = new HttpShadowLogSink({
|
|
61
|
+
// endpoint: resolvedOptions.shadowLogEndpoint,
|
|
62
|
+
// apiKey: resolvedOptions.apiKey,
|
|
63
|
+
// });
|
|
64
|
+
// }
|
|
65
|
+
const shadowLogSink = undefined;
|
|
66
|
+
// Step 6: Wire application service
|
|
67
|
+
this.service = new ShieldApplicationService({
|
|
68
|
+
patternRepository: patternRepo,
|
|
69
|
+
telemetrySink,
|
|
70
|
+
toolPolicy,
|
|
71
|
+
sentinel,
|
|
72
|
+
shadowLogSink,
|
|
73
|
+
sdkVersion: "0.2.0",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Resolves baseUrl into individual endpoint URLs
|
|
78
|
+
* baseUrl takes precedence over individual endpoint options
|
|
79
|
+
*/
|
|
80
|
+
resolveEndpoints(options) {
|
|
81
|
+
if (options.baseUrl) {
|
|
82
|
+
// Remove trailing slash for consistency
|
|
83
|
+
const baseUrl = options.baseUrl.replace(/\/$/, '');
|
|
84
|
+
return {
|
|
85
|
+
...options,
|
|
86
|
+
apiEndpoint: `${baseUrl}/api/v1/signal`,
|
|
87
|
+
sentinelEndpoint: `${baseUrl}/api/v1/verify-prompt`,
|
|
88
|
+
shadowLogEndpoint: `${baseUrl}/api/v1/shadow-log`,
|
|
89
|
+
manifestUrl: `${baseUrl}/api/v1/definitions`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// No baseUrl, use individual options as-is
|
|
93
|
+
return options;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Main wrapper for LLM calls
|
|
97
|
+
*
|
|
98
|
+
* @param llmCall - Function that executes the LLM call
|
|
99
|
+
* @param options - Optional: prompt for pre-LLM scanning, request context
|
|
100
|
+
*
|
|
101
|
+
* @throws ShieldBlockError if an injection or unauthorized tool is detected
|
|
102
|
+
* @throws Other errors from the LLM provider or network failures
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* // With optional prompt for pre-LLM scanning (fixes Gap 3)
|
|
107
|
+
* const response = await shield.wrap(
|
|
108
|
+
* () => openai.chat.completions.create({...}),
|
|
109
|
+
* { prompt: userInput }
|
|
110
|
+
* );
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
async wrap(llmCall, options) {
|
|
114
|
+
return this.service.wrap(llmCall, options);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Scan a raw prompt for injection attempts (standalone use)
|
|
118
|
+
*
|
|
119
|
+
* @param prompt - The user input to scan
|
|
120
|
+
* @throws ShieldBlockError if injection is detected
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* try {
|
|
125
|
+
* await shield.scanPrompt(userInput);
|
|
126
|
+
* // Safe to proceed
|
|
127
|
+
* } catch (err) {
|
|
128
|
+
* if (err instanceof ShieldBlockError) {
|
|
129
|
+
* // Attack detected
|
|
130
|
+
* }
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
async scanPrompt(prompt) {
|
|
135
|
+
return this.service.scanPrompt(prompt);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Update allowed tools at runtime
|
|
139
|
+
*
|
|
140
|
+
* @param tools - New list of allowed tool names
|
|
141
|
+
*/
|
|
142
|
+
setAllowedTools(tools) {
|
|
143
|
+
return this.service.setAllowedTools(tools);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get Shield status and diagnostics
|
|
147
|
+
*/
|
|
148
|
+
getStatus() {
|
|
149
|
+
return this.service.getStatus();
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Graceful shutdown: flushes telemetry and releases resources
|
|
153
|
+
* Call this before process exit
|
|
154
|
+
*/
|
|
155
|
+
destroy() {
|
|
156
|
+
return this.service.destroy();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// ============================================================================
|
|
160
|
+
// Public Exports
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// Error class
|
|
163
|
+
export { ShieldBlockError };
|
|
164
|
+
// Infrastructure adapter exports (for advanced/custom usage)
|
|
165
|
+
export { BundledPatternRepository, RemotePatternRepository } from './infrastructure/patterns/index.js';
|
|
166
|
+
// Utility exports (for middleware & advanced use)
|
|
167
|
+
export { normalizePrompt, normalizePrompts, jitter } from './application/utils/index.js';
|
|
168
|
+
export { HttpSignalSink } from './infrastructure/telemetry/index.js';
|
|
169
|
+
// Layer 2 Sentinel exports
|
|
170
|
+
export { LLMSentinel } from './infrastructure/sentinel/LLMSentinel.js';
|
|
171
|
+
export { HttpShadowLogSink } from './infrastructure/telemetry/HttpShadowLogSink.js';
|
|
172
|
+
export { ShieldApplicationService } from './application/ShieldApplicationService.js';
|
|
173
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenRouter LLM Provider
|
|
3
|
+
* Adapter: implements ILLMProvider for OpenRouter
|
|
4
|
+
* Uses native fetch — zero dependencies (no openai npm package)
|
|
5
|
+
*/
|
|
6
|
+
import { ILLMProvider, LLMRequest, LLMResponse } from "../../application/ports/ILLMProvider";
|
|
7
|
+
export interface OpenRouterConfig {
|
|
8
|
+
apiKey: string;
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
siteUrl?: string;
|
|
11
|
+
siteTitle?: string;
|
|
12
|
+
defaultModel?: string;
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare class OpenRouterProvider implements ILLMProvider {
|
|
16
|
+
private readonly config;
|
|
17
|
+
readonly providerName = "openrouter";
|
|
18
|
+
private readonly baseUrl;
|
|
19
|
+
private readonly timeoutMs;
|
|
20
|
+
constructor(config: OpenRouterConfig);
|
|
21
|
+
/**
|
|
22
|
+
* Execute an LLM call via OpenRouter.
|
|
23
|
+
* Implements ILLMProvider.complete()
|
|
24
|
+
*/
|
|
25
|
+
complete(request: LLMRequest): Promise<LLMResponse>;
|
|
26
|
+
/**
|
|
27
|
+
* Create an AbortSignal for request timeout.
|
|
28
|
+
* Node.js 17+ supports AbortSignal.timeout()
|
|
29
|
+
*/
|
|
30
|
+
private createAbortSignal;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=OpenRouterProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenRouterProvider.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/llm/OpenRouterProvider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,YAAY,EACZ,UAAU,EACV,WAAW,EAEZ,MAAM,sCAAsC,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,kBAAmB,YAAW,YAAY;IAMzC,OAAO,CAAC,QAAQ,CAAC,MAAM;IALnC,QAAQ,CAAC,YAAY,gBAAgB;IAErC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEN,MAAM,EAAE,gBAAgB;IASrD;;;OAGG;IACG,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IA0EzD;;;OAGG;IACH,OAAO,CAAC,iBAAiB;CA2D1B"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenRouter LLM Provider
|
|
3
|
+
* Adapter: implements ILLMProvider for OpenRouter
|
|
4
|
+
* Uses native fetch — zero dependencies (no openai npm package)
|
|
5
|
+
*/
|
|
6
|
+
import { ProviderError, } from '../../application/ports/ILLMProvider.js';
|
|
7
|
+
export class OpenRouterProvider {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
this.providerName = "openrouter";
|
|
11
|
+
this.baseUrl = config.baseUrl ?? "https://openrouter.ai/api/v1";
|
|
12
|
+
this.timeoutMs = config.timeoutMs ?? 30000;
|
|
13
|
+
if (!config.apiKey) {
|
|
14
|
+
throw new Error("[OpenRouterProvider] apiKey is required");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Execute an LLM call via OpenRouter.
|
|
19
|
+
* Implements ILLMProvider.complete()
|
|
20
|
+
*/
|
|
21
|
+
async complete(request) {
|
|
22
|
+
const model = request.model || this.config.defaultModel || "openai/gpt-4o";
|
|
23
|
+
// Build the request body — OpenAI-compatible format
|
|
24
|
+
const body = {
|
|
25
|
+
model,
|
|
26
|
+
messages: request.messages,
|
|
27
|
+
...(request.tools && { tools: request.tools }),
|
|
28
|
+
...(request.temperature !== undefined && { temperature: request.temperature }),
|
|
29
|
+
...(request.maxTokens !== undefined && { max_tokens: request.maxTokens }),
|
|
30
|
+
// Pass through any additional provider-specific parameters
|
|
31
|
+
...Object.fromEntries(Object.entries(request).filter(([key]) => ![
|
|
32
|
+
"messages",
|
|
33
|
+
"model",
|
|
34
|
+
"tools",
|
|
35
|
+
"temperature",
|
|
36
|
+
"maxTokens",
|
|
37
|
+
].includes(key))),
|
|
38
|
+
};
|
|
39
|
+
try {
|
|
40
|
+
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: {
|
|
43
|
+
"Content-Type": "application/json",
|
|
44
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
45
|
+
// OpenRouter required headers
|
|
46
|
+
"HTTP-Referer": this.config.siteUrl ?? "",
|
|
47
|
+
"X-Title": this.config.siteTitle ?? "Tracerny",
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify(body),
|
|
50
|
+
signal: this.createAbortSignal(),
|
|
51
|
+
});
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
const errorBody = await response.text().catch(() => "");
|
|
54
|
+
throw new ProviderError(`OpenRouter returned ${response.status}: ${response.statusText}\n${errorBody}`, "openrouter", response.status);
|
|
55
|
+
}
|
|
56
|
+
// Response shape is OpenAI-compatible — cast directly
|
|
57
|
+
const data = (await response.json());
|
|
58
|
+
return data;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (error instanceof ProviderError) {
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
65
|
+
throw new ProviderError(`Network error: ${error.message}`, "openrouter", undefined, error);
|
|
66
|
+
}
|
|
67
|
+
throw new ProviderError(`OpenRouter call failed: ${error instanceof Error ? error.message : String(error)}`, "openrouter", undefined, error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create an AbortSignal for request timeout.
|
|
72
|
+
* Node.js 17+ supports AbortSignal.timeout()
|
|
73
|
+
*/
|
|
74
|
+
createAbortSignal() {
|
|
75
|
+
// Try Node.js 17+ AbortSignal.timeout()
|
|
76
|
+
if (AbortSignal && "timeout" in AbortSignal) {
|
|
77
|
+
try {
|
|
78
|
+
return AbortSignal.timeout(this.timeoutMs);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Fallback if timeout() not available
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Fallback: use AbortController with timer
|
|
85
|
+
const controller = new AbortController();
|
|
86
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
87
|
+
// Clean up timeout on early resolution
|
|
88
|
+
const originalSignal = controller.signal;
|
|
89
|
+
const wrappedSignal = new (class {
|
|
90
|
+
constructor() {
|
|
91
|
+
this.aborted = originalSignal.aborted;
|
|
92
|
+
this.addEventListener = (type, listener, options) => {
|
|
93
|
+
originalSignal.addEventListener(type, listener, options);
|
|
94
|
+
};
|
|
95
|
+
this.removeEventListener = (type, listener, options) => {
|
|
96
|
+
originalSignal.removeEventListener(type, listener, options);
|
|
97
|
+
};
|
|
98
|
+
this.dispatchEvent = (event) => {
|
|
99
|
+
clearTimeout(timeoutId);
|
|
100
|
+
return originalSignal.dispatchEvent(event);
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
get onabort() {
|
|
104
|
+
return originalSignal.onabort;
|
|
105
|
+
}
|
|
106
|
+
set onabort(handler) {
|
|
107
|
+
originalSignal.onabort = handler;
|
|
108
|
+
}
|
|
109
|
+
get reason() {
|
|
110
|
+
return originalSignal.reason;
|
|
111
|
+
}
|
|
112
|
+
throwIfAborted() {
|
|
113
|
+
originalSignal.throwIfAborted?.();
|
|
114
|
+
}
|
|
115
|
+
})();
|
|
116
|
+
return wrappedSignal;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=OpenRouterProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenRouterProvider.js","sourceRoot":"","sources":["../../../src/infrastructure/llm/OpenRouterProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/llm/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|