@idevconn/ai-chat-be 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/dist/ai-chat.module.d.ts +6 -0
  2. package/dist/ai-chat.module.d.ts.map +1 -0
  3. package/dist/ai-chat.module.js +109 -0
  4. package/dist/ai-chat.module.js.map +1 -0
  5. package/dist/audit/audit.service.d.ts +39 -0
  6. package/dist/audit/audit.service.d.ts.map +1 -0
  7. package/dist/audit/audit.service.js +139 -0
  8. package/dist/audit/audit.service.js.map +1 -0
  9. package/dist/chat/chat.controller.d.ts +20 -0
  10. package/dist/chat/chat.controller.d.ts.map +1 -0
  11. package/dist/chat/chat.controller.js +104 -0
  12. package/dist/chat/chat.controller.js.map +1 -0
  13. package/dist/chat/chat.service.d.ts +15 -0
  14. package/dist/chat/chat.service.d.ts.map +1 -0
  15. package/dist/chat/chat.service.js +95 -0
  16. package/dist/chat/chat.service.js.map +1 -0
  17. package/dist/guards/api-key.guard.d.ts +8 -0
  18. package/dist/guards/api-key.guard.d.ts.map +1 -0
  19. package/dist/guards/api-key.guard.js +44 -0
  20. package/dist/guards/api-key.guard.js.map +1 -0
  21. package/dist/guards/llm-injection-classifier.d.ts +17 -0
  22. package/dist/guards/llm-injection-classifier.d.ts.map +1 -0
  23. package/dist/guards/llm-injection-classifier.js +82 -0
  24. package/dist/guards/llm-injection-classifier.js.map +1 -0
  25. package/dist/guards/pii.guard.d.ts +14 -0
  26. package/dist/guards/pii.guard.d.ts.map +1 -0
  27. package/dist/guards/pii.guard.js +67 -0
  28. package/dist/guards/pii.guard.js.map +1 -0
  29. package/dist/guards/prompt-injection.guard.d.ts +9 -0
  30. package/dist/guards/prompt-injection.guard.d.ts.map +1 -0
  31. package/dist/guards/prompt-injection.guard.js +157 -0
  32. package/dist/guards/prompt-injection.guard.js.map +1 -0
  33. package/dist/guards/rate-limit.guard.d.ts +8 -0
  34. package/dist/guards/rate-limit.guard.d.ts.map +1 -0
  35. package/dist/guards/rate-limit.guard.js +59 -0
  36. package/dist/guards/rate-limit.guard.js.map +1 -0
  37. package/dist/guards/topic-relevance.guard.d.ts +21 -0
  38. package/dist/guards/topic-relevance.guard.d.ts.map +1 -0
  39. package/dist/guards/topic-relevance.guard.js +59 -0
  40. package/dist/guards/topic-relevance.guard.js.map +1 -0
  41. package/dist/index.d.ts +22 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +31 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/intent/embedding-intent-router.d.ts +23 -0
  46. package/dist/intent/embedding-intent-router.d.ts.map +1 -0
  47. package/dist/intent/embedding-intent-router.js +103 -0
  48. package/dist/intent/embedding-intent-router.js.map +1 -0
  49. package/dist/intent/intent-router.interface.d.ts +8 -0
  50. package/dist/intent/intent-router.interface.d.ts.map +1 -0
  51. package/dist/intent/intent-router.interface.js +5 -0
  52. package/dist/intent/intent-router.interface.js.map +1 -0
  53. package/dist/intent/intent.types.d.ts +7 -0
  54. package/dist/intent/intent.types.d.ts.map +1 -0
  55. package/dist/intent/intent.types.js +3 -0
  56. package/dist/intent/intent.types.js.map +1 -0
  57. package/dist/orchestrator/default.orchestrator.d.ts +36 -0
  58. package/dist/orchestrator/default.orchestrator.d.ts.map +1 -0
  59. package/dist/orchestrator/default.orchestrator.js +231 -0
  60. package/dist/orchestrator/default.orchestrator.js.map +1 -0
  61. package/dist/orchestrator/input-sanitizer.d.ts +8 -0
  62. package/dist/orchestrator/input-sanitizer.d.ts.map +1 -0
  63. package/dist/orchestrator/input-sanitizer.js +36 -0
  64. package/dist/orchestrator/input-sanitizer.js.map +1 -0
  65. package/dist/orchestrator/orchestrator.interface.d.ts +6 -0
  66. package/dist/orchestrator/orchestrator.interface.d.ts.map +1 -0
  67. package/dist/orchestrator/orchestrator.interface.js +5 -0
  68. package/dist/orchestrator/orchestrator.interface.js.map +1 -0
  69. package/dist/orchestrator/prompt-builder.d.ts +12 -0
  70. package/dist/orchestrator/prompt-builder.d.ts.map +1 -0
  71. package/dist/orchestrator/prompt-builder.js +55 -0
  72. package/dist/orchestrator/prompt-builder.js.map +1 -0
  73. package/dist/orchestrator/prompt-normalizer.d.ts +9 -0
  74. package/dist/orchestrator/prompt-normalizer.d.ts.map +1 -0
  75. package/dist/orchestrator/prompt-normalizer.js +77 -0
  76. package/dist/orchestrator/prompt-normalizer.js.map +1 -0
  77. package/dist/orchestrator/response-sanitizer.d.ts +26 -0
  78. package/dist/orchestrator/response-sanitizer.d.ts.map +1 -0
  79. package/dist/orchestrator/response-sanitizer.js +127 -0
  80. package/dist/orchestrator/response-sanitizer.js.map +1 -0
  81. package/dist/orchestrator/response-validator.d.ts +10 -0
  82. package/dist/orchestrator/response-validator.d.ts.map +1 -0
  83. package/dist/orchestrator/response-validator.js +31 -0
  84. package/dist/orchestrator/response-validator.js.map +1 -0
  85. package/dist/providers/gemini.provider.d.ts +13 -0
  86. package/dist/providers/gemini.provider.d.ts.map +1 -0
  87. package/dist/providers/gemini.provider.js +132 -0
  88. package/dist/providers/gemini.provider.js.map +1 -0
  89. package/dist/providers/grok.provider.d.ts +11 -0
  90. package/dist/providers/grok.provider.d.ts.map +1 -0
  91. package/dist/providers/grok.provider.js +69 -0
  92. package/dist/providers/grok.provider.js.map +1 -0
  93. package/dist/providers/openai.provider.d.ts +12 -0
  94. package/dist/providers/openai.provider.d.ts.map +1 -0
  95. package/dist/providers/openai.provider.js +87 -0
  96. package/dist/providers/openai.provider.js.map +1 -0
  97. package/dist/providers/provider-registry.d.ts +17 -0
  98. package/dist/providers/provider-registry.d.ts.map +1 -0
  99. package/dist/providers/provider-registry.js +42 -0
  100. package/dist/providers/provider-registry.js.map +1 -0
  101. package/dist/providers/provider-settings.d.ts +12 -0
  102. package/dist/providers/provider-settings.d.ts.map +1 -0
  103. package/dist/providers/provider-settings.js +3 -0
  104. package/dist/providers/provider-settings.js.map +1 -0
  105. package/dist/providers/provider.factory.d.ts +18 -0
  106. package/dist/providers/provider.factory.d.ts.map +1 -0
  107. package/dist/providers/provider.factory.js +107 -0
  108. package/dist/providers/provider.factory.js.map +1 -0
  109. package/dist/rag/chunker.d.ts +7 -0
  110. package/dist/rag/chunker.d.ts.map +1 -0
  111. package/dist/rag/chunker.js +32 -0
  112. package/dist/rag/chunker.js.map +1 -0
  113. package/dist/rag/rag.service.d.ts +20 -0
  114. package/dist/rag/rag.service.d.ts.map +1 -0
  115. package/dist/rag/rag.service.js +171 -0
  116. package/dist/rag/rag.service.js.map +1 -0
  117. package/dist/session/session.service.d.ts +32 -0
  118. package/dist/session/session.service.d.ts.map +1 -0
  119. package/dist/session/session.service.js +161 -0
  120. package/dist/session/session.service.js.map +1 -0
  121. package/dist/types/chat.types.d.ts +31 -0
  122. package/dist/types/chat.types.d.ts.map +1 -0
  123. package/dist/types/chat.types.js +3 -0
  124. package/dist/types/chat.types.js.map +1 -0
  125. package/dist/types/config.types.d.ts +139 -0
  126. package/dist/types/config.types.d.ts.map +1 -0
  127. package/dist/types/config.types.js +5 -0
  128. package/dist/types/config.types.js.map +1 -0
  129. package/dist/types/index.d.ts +4 -0
  130. package/dist/types/index.d.ts.map +1 -0
  131. package/dist/types/index.js +20 -0
  132. package/dist/types/index.js.map +1 -0
  133. package/dist/types/provider.types.d.ts +15 -0
  134. package/dist/types/provider.types.d.ts.map +1 -0
  135. package/dist/types/provider.types.js +3 -0
  136. package/dist/types/provider.types.js.map +1 -0
  137. package/dist/utils/cosine-similarity.d.ts +2 -0
  138. package/dist/utils/cosine-similarity.d.ts.map +1 -0
  139. package/dist/utils/cosine-similarity.js +21 -0
  140. package/dist/utils/cosine-similarity.js.map +1 -0
  141. package/dist/utils/error-sanitizer.d.ts +8 -0
  142. package/dist/utils/error-sanitizer.d.ts.map +1 -0
  143. package/dist/utils/error-sanitizer.js +44 -0
  144. package/dist/utils/error-sanitizer.js.map +1 -0
  145. package/dist/utils/index.d.ts +6 -0
  146. package/dist/utils/index.d.ts.map +1 -0
  147. package/dist/utils/index.js +22 -0
  148. package/dist/utils/index.js.map +1 -0
  149. package/dist/utils/logger.d.ts +11 -0
  150. package/dist/utils/logger.d.ts.map +1 -0
  151. package/dist/utils/logger.js +47 -0
  152. package/dist/utils/logger.js.map +1 -0
  153. package/dist/utils/pii-detector.d.ts +8 -0
  154. package/dist/utils/pii-detector.d.ts.map +1 -0
  155. package/dist/utils/pii-detector.js +82 -0
  156. package/dist/utils/pii-detector.js.map +1 -0
  157. package/dist/utils/retry.d.ts +8 -0
  158. package/dist/utils/retry.d.ts.map +1 -0
  159. package/dist/utils/retry.js +33 -0
  160. package/dist/utils/retry.js.map +1 -0
  161. package/dist/utils/session-token.d.ts +8 -0
  162. package/dist/utils/session-token.d.ts.map +1 -0
  163. package/dist/utils/session-token.js +46 -0
  164. package/dist/utils/session-token.js.map +1 -0
  165. package/dist/utils/sse-parser.d.ts +5 -0
  166. package/dist/utils/sse-parser.d.ts.map +1 -0
  167. package/dist/utils/sse-parser.js +45 -0
  168. package/dist/utils/sse-parser.js.map +1 -0
  169. package/dist/utils/text.d.ts +4 -0
  170. package/dist/utils/text.d.ts.map +1 -0
  171. package/dist/utils/text.js +25 -0
  172. package/dist/utils/text.js.map +1 -0
  173. package/package.json +62 -0
@@ -0,0 +1,6 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import { AiChatModuleConfig } from './types';
3
+ export declare class AiChatModule {
4
+ static forRoot(config: AiChatModuleConfig): DynamicModule;
5
+ }
6
+ //# sourceMappingURL=ai-chat.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-chat.module.d.ts","sourceRoot":"","sources":["../src/ai-chat.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,gBAAgB,CAAC;AAGvD,OAAO,EAAkB,kBAAkB,EAAE,MAAM,SAAS,CAAC;AA0B7D,qBACa,YAAY;IACvB,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,kBAAkB,GAAG,aAAa;CAkE1D"}
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var AiChatModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.AiChatModule = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const core_1 = require("@nestjs/core");
13
+ const throttler_1 = require("@nestjs/throttler");
14
+ const types_1 = require("./types");
15
+ const chat_controller_1 = require("./chat/chat.controller");
16
+ const chat_service_1 = require("./chat/chat.service");
17
+ const session_service_1 = require("./session/session.service");
18
+ const provider_factory_1 = require("./providers/provider.factory");
19
+ const rag_service_1 = require("./rag/rag.service");
20
+ const default_orchestrator_1 = require("./orchestrator/default.orchestrator");
21
+ const prompt_builder_1 = require("./orchestrator/prompt-builder");
22
+ const prompt_normalizer_1 = require("./orchestrator/prompt-normalizer");
23
+ const input_sanitizer_1 = require("./orchestrator/input-sanitizer");
24
+ const response_validator_1 = require("./orchestrator/response-validator");
25
+ const response_sanitizer_1 = require("./orchestrator/response-sanitizer");
26
+ const api_key_guard_1 = require("./guards/api-key.guard");
27
+ const prompt_injection_guard_1 = require("./guards/prompt-injection.guard");
28
+ const topic_relevance_guard_1 = require("./guards/topic-relevance.guard");
29
+ const llm_injection_classifier_1 = require("./guards/llm-injection-classifier");
30
+ const pii_guard_1 = require("./guards/pii.guard");
31
+ const rate_limit_guard_1 = require("./guards/rate-limit.guard");
32
+ const embedding_intent_router_1 = require("./intent/embedding-intent-router");
33
+ const audit_service_1 = require("./audit/audit.service");
34
+ const logger_1 = require("./utils/logger");
35
+ const DEFAULT_PER_KEY = { limit: 20, ttlMs: 60_000 };
36
+ const DEFAULT_PER_SESSION = { limit: 5, ttlMs: 60_000 };
37
+ const DEFAULT_PER_IP = { limit: 60, ttlMs: 60_000 };
38
+ let AiChatModule = AiChatModule_1 = class AiChatModule {
39
+ static forRoot(config) {
40
+ (0, logger_1.setBootLogsEnabled)(config.log ?? process.env.AI_CHAT_LOG !== 'false');
41
+ const rateLimit = config.rateLimit ?? {};
42
+ const perKey = rateLimit.perKey ?? {
43
+ limit: DEFAULT_PER_KEY.limit,
44
+ windowMs: DEFAULT_PER_KEY.ttlMs,
45
+ };
46
+ const perSession = rateLimit.perSession ?? {
47
+ limit: DEFAULT_PER_SESSION.limit,
48
+ windowMs: DEFAULT_PER_SESSION.ttlMs,
49
+ };
50
+ const perIp = rateLimit.perIp ?? {
51
+ limit: DEFAULT_PER_IP.limit,
52
+ windowMs: DEFAULT_PER_IP.ttlMs,
53
+ };
54
+ return {
55
+ module: AiChatModule_1,
56
+ imports: [
57
+ throttler_1.ThrottlerModule.forRoot([
58
+ {
59
+ name: 'ai-chat-key',
60
+ ttl: perKey.windowMs,
61
+ limit: perKey.limit,
62
+ },
63
+ {
64
+ name: 'ai-chat-session',
65
+ ttl: perSession.windowMs,
66
+ limit: perSession.limit,
67
+ },
68
+ {
69
+ name: 'ai-chat-ip',
70
+ ttl: perIp.windowMs,
71
+ limit: perIp.limit,
72
+ },
73
+ ]),
74
+ ],
75
+ controllers: [chat_controller_1.ChatController],
76
+ providers: [
77
+ {
78
+ provide: types_1.AI_CHAT_CONFIG,
79
+ useValue: config,
80
+ },
81
+ core_1.Reflector,
82
+ session_service_1.SessionService,
83
+ provider_factory_1.ProviderFactory,
84
+ rag_service_1.RagService,
85
+ default_orchestrator_1.DefaultOrchestrator,
86
+ prompt_builder_1.PromptBuilder,
87
+ prompt_normalizer_1.PromptNormalizer,
88
+ input_sanitizer_1.InputSanitizer,
89
+ response_validator_1.ResponseValidator,
90
+ response_sanitizer_1.ResponseSanitizer,
91
+ chat_service_1.ChatService,
92
+ api_key_guard_1.ApiKeyGuard,
93
+ rate_limit_guard_1.RateLimitGuard,
94
+ prompt_injection_guard_1.PromptInjectionGuard,
95
+ llm_injection_classifier_1.LlmInjectionClassifier,
96
+ topic_relevance_guard_1.TopicRelevanceGuard,
97
+ pii_guard_1.PiiGuard,
98
+ embedding_intent_router_1.EmbeddingIntentRouter,
99
+ audit_service_1.AuditService,
100
+ ],
101
+ exports: [chat_service_1.ChatService, session_service_1.SessionService, provider_factory_1.ProviderFactory, embedding_intent_router_1.EmbeddingIntentRouter, audit_service_1.AuditService],
102
+ };
103
+ }
104
+ };
105
+ exports.AiChatModule = AiChatModule;
106
+ exports.AiChatModule = AiChatModule = AiChatModule_1 = __decorate([
107
+ (0, common_1.Module)({})
108
+ ], AiChatModule);
109
+ //# sourceMappingURL=ai-chat.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-chat.module.js","sourceRoot":"","sources":["../src/ai-chat.module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { AiChatModuleConfig, AuditEvent } from '../types';
2
+ export declare const AUDIT_EVENT_NAME = "ai-chat.request.completed";
3
+ export type AuditEventPartial = Partial<AuditEvent> & {
4
+ ts?: number;
5
+ inputLength?: number;
6
+ outputLength?: number;
7
+ injectionFlags?: string[];
8
+ piiTypes?: string[];
9
+ intent?: AuditEvent['intent'];
10
+ outcome?: AuditEvent['outcome'];
11
+ provider?: AuditEvent['provider'];
12
+ };
13
+ export declare class AuditEventBuilder {
14
+ private readonly emitter;
15
+ private readonly start;
16
+ private readonly draft;
17
+ constructor(emitter: AuditService);
18
+ setSession(rawSessionId: string): this;
19
+ setApiKey(apiKey: string | undefined | null): this;
20
+ setInput(text: string): this;
21
+ setIntent(intent: AuditEvent['intent']): this;
22
+ setProvider(provider: AuditEvent['provider']): this;
23
+ addInjectionFlag(reason: string): this;
24
+ setPiiTypes(types: string[]): this;
25
+ recordOutputChunk(chunk: string): this;
26
+ setOutcome(outcome: AuditEvent['outcome'], error?: string): this;
27
+ emit(): AuditEvent;
28
+ }
29
+ export declare class AuditService {
30
+ private readonly config;
31
+ private readonly emitter;
32
+ private readonly enabled;
33
+ private readonly sink?;
34
+ constructor(config: AiChatModuleConfig);
35
+ start(): AuditEventBuilder;
36
+ emit(event: AuditEvent): void;
37
+ on(listener: (event: AuditEvent) => void): () => void;
38
+ }
39
+ //# sourceMappingURL=audit.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.service.d.ts","sourceRoot":"","sources":["../../src/audit/audit.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,kBAAkB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAG1E,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG;IACpD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC9B,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;CACnC,CAAC;AAOF,qBAAa,iBAAiB;IAahB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CASpB;gBAE2B,OAAO,EAAE,YAAY;IAElD,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAKtC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI;IAKlD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM5B,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,IAAI;IAK7C,WAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,GAAG,IAAI;IAKnD,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKtC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAKlC,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKtC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAMhE,IAAI,IAAI,UAAU;CAmBnB;AAED,qBACa,YAAY;IAKa,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJ3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAA8C;gBAEf,MAAM,EAAE,kBAAkB;IAK/E,KAAK,IAAI,iBAAiB;IAI1B,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAmB7B,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;CAItD"}
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.AuditService = exports.AuditEventBuilder = exports.AUDIT_EVENT_NAME = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const crypto_1 = require("crypto");
18
+ const events_1 = require("events");
19
+ const types_1 = require("../types");
20
+ const logger_1 = require("../utils/logger");
21
+ exports.AUDIT_EVENT_NAME = 'ai-chat.request.completed';
22
+ class AuditEventBuilder {
23
+ emitter;
24
+ start = Date.now();
25
+ draft = {
26
+ ts: this.start,
27
+ inputLength: 0,
28
+ outputLength: 0,
29
+ injectionFlags: [],
30
+ piiTypes: [],
31
+ intent: 'docs_question',
32
+ provider: 'unknown',
33
+ outcome: 'success',
34
+ };
35
+ constructor(emitter) {
36
+ this.emitter = emitter;
37
+ }
38
+ setSession(rawSessionId) {
39
+ this.draft.sessionHash = sha256Hex(rawSessionId);
40
+ return this;
41
+ }
42
+ setApiKey(apiKey) {
43
+ this.draft.apiKeyHash = apiKey ? sha256Hex(apiKey) : 'anonymous';
44
+ return this;
45
+ }
46
+ setInput(text) {
47
+ this.draft.inputHash = sha256Hex(text);
48
+ this.draft.inputLength = text.length;
49
+ return this;
50
+ }
51
+ setIntent(intent) {
52
+ this.draft.intent = intent;
53
+ return this;
54
+ }
55
+ setProvider(provider) {
56
+ this.draft.provider = provider;
57
+ return this;
58
+ }
59
+ addInjectionFlag(reason) {
60
+ this.draft.injectionFlags?.push(reason);
61
+ return this;
62
+ }
63
+ setPiiTypes(types) {
64
+ this.draft.piiTypes = types;
65
+ return this;
66
+ }
67
+ recordOutputChunk(chunk) {
68
+ this.draft.outputLength = (this.draft.outputLength ?? 0) + chunk.length;
69
+ return this;
70
+ }
71
+ setOutcome(outcome, error) {
72
+ this.draft.outcome = outcome;
73
+ if (error)
74
+ this.draft.error = error;
75
+ return this;
76
+ }
77
+ emit() {
78
+ const event = {
79
+ ts: this.start,
80
+ sessionHash: this.draft.sessionHash ?? 'unknown',
81
+ apiKeyHash: this.draft.apiKeyHash ?? 'anonymous',
82
+ inputHash: this.draft.inputHash ?? '',
83
+ inputLength: this.draft.inputLength ?? 0,
84
+ outputLength: this.draft.outputLength ?? 0,
85
+ intent: this.draft.intent ?? 'docs_question',
86
+ injectionFlags: this.draft.injectionFlags ?? [],
87
+ piiTypes: this.draft.piiTypes ?? [],
88
+ provider: this.draft.provider ?? 'unknown',
89
+ latencyMs: Date.now() - this.start,
90
+ outcome: this.draft.outcome ?? 'success',
91
+ error: this.draft.error,
92
+ };
93
+ this.emitter.emit(event);
94
+ return event;
95
+ }
96
+ }
97
+ exports.AuditEventBuilder = AuditEventBuilder;
98
+ let AuditService = class AuditService {
99
+ config;
100
+ emitter = new events_1.EventEmitter();
101
+ enabled;
102
+ sink;
103
+ constructor(config) {
104
+ this.config = config;
105
+ this.enabled = config.audit?.enabled !== false;
106
+ this.sink = config.audit?.sink;
107
+ }
108
+ start() {
109
+ return new AuditEventBuilder(this);
110
+ }
111
+ emit(event) {
112
+ if (!this.enabled)
113
+ return;
114
+ this.emitter.emit(exports.AUDIT_EVENT_NAME, event);
115
+ if (this.sink) {
116
+ Promise.resolve(this.sink(event)).catch((err) => {
117
+ logger_1.aiChatLogger.error(`Audit sink failed: ${err instanceof Error ? err.message : err}`);
118
+ });
119
+ return;
120
+ }
121
+ if (process.env.NODE_ENV !== 'production') {
122
+ logger_1.aiChatLogger.debug?.(`audit ${event.outcome} intent=${event.intent} ${event.latencyMs}ms in=${event.inputLength} out=${event.outputLength} flags=${event.injectionFlags.length} pii=${event.piiTypes.length}`);
123
+ }
124
+ }
125
+ on(listener) {
126
+ this.emitter.on(exports.AUDIT_EVENT_NAME, listener);
127
+ return () => this.emitter.off(exports.AUDIT_EVENT_NAME, listener);
128
+ }
129
+ };
130
+ exports.AuditService = AuditService;
131
+ exports.AuditService = AuditService = __decorate([
132
+ (0, common_1.Injectable)(),
133
+ __param(0, (0, common_1.Inject)(types_1.AI_CHAT_CONFIG)),
134
+ __metadata("design:paramtypes", [Object])
135
+ ], AuditService);
136
+ function sha256Hex(text) {
137
+ return (0, crypto_1.createHash)('sha256').update(text).digest('hex');
138
+ }
139
+ //# sourceMappingURL=audit.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.service.js","sourceRoot":"","sources":["../../src/audit/audit.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ interface Response {
2
+ setHeader(name: string, value: string): void;
3
+ write(chunk: string): void;
4
+ end(): void;
5
+ }
6
+ import { ChatService } from './chat.service';
7
+ import { ProviderFactory } from '../providers/provider.factory';
8
+ import { ChatRequestDto } from '../types';
9
+ export declare class ChatController {
10
+ private readonly chatService;
11
+ private readonly providerFactory;
12
+ constructor(chatService: ChatService, providerFactory: ProviderFactory);
13
+ chat(dto: ChatRequestDto, res: Response, apiKey?: string): Promise<void>;
14
+ createSession(): {
15
+ sessionId: string;
16
+ };
17
+ deleteSession(id: string): void;
18
+ }
19
+ export {};
20
+ //# sourceMappingURL=chat.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.controller.d.ts","sourceRoot":"","sources":["../../src/chat/chat.controller.ts"],"names":[],"mappings":"AAcA,UAAU,QAAQ;IAChB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,IAAI,IAAI,CAAC;CACb;AACD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAW1C,qBAGa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,eAAe;gBADf,WAAW,EAAE,WAAW,EACxB,eAAe,EAAE,eAAe;IAU7C,IAAI,CACA,GAAG,EAAE,cAAc,EACpB,GAAG,EAAE,QAAQ,EACE,MAAM,CAAC,EAAE,MAAM,GACpC,OAAO,CAAC,IAAI,CAAC;IAoChB,aAAa,IAAI;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;IAOtC,aAAa,CAAc,EAAE,EAAE,MAAM,GAAG,IAAI;CAG7C"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ChatController = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const chat_service_1 = require("./chat.service");
18
+ const api_key_guard_1 = require("../guards/api-key.guard");
19
+ const rate_limit_guard_1 = require("../guards/rate-limit.guard");
20
+ const provider_factory_1 = require("../providers/provider.factory");
21
+ const sse_parser_1 = require("../utils/sse-parser");
22
+ const error_sanitizer_1 = require("../utils/error-sanitizer");
23
+ const logger_1 = require("../utils/logger");
24
+ const PublicChat = () => (0, common_1.SetMetadata)('isPublic', true);
25
+ let ChatController = class ChatController {
26
+ chatService;
27
+ providerFactory;
28
+ constructor(chatService, providerFactory) {
29
+ this.chatService = chatService;
30
+ this.providerFactory = providerFactory;
31
+ }
32
+ async chat(dto, res, apiKey) {
33
+ if (!this.providerFactory.isAvailable()) {
34
+ throw new common_1.ServiceUnavailableException('No LLM provider available');
35
+ }
36
+ res.setHeader('Content-Type', 'text/event-stream');
37
+ res.setHeader('Cache-Control', 'no-cache');
38
+ res.setHeader('Connection', 'keep-alive');
39
+ try {
40
+ for await (const event of this.chatService.chat(dto.sessionId, dto.message, { apiKey })) {
41
+ res.write((0, sse_parser_1.formatSseEvent)(event));
42
+ if (event.type === 'done' || event.type === 'error') {
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ catch (error) {
48
+ logger_1.aiChatLogger.error(`Chat controller caught: ${error instanceof Error ? error.message : error}`);
49
+ const sanitized = (0, error_sanitizer_1.sanitizeError)(error);
50
+ res.write((0, sse_parser_1.formatSseEvent)({
51
+ type: 'error',
52
+ error: sanitized.message,
53
+ }));
54
+ }
55
+ res.end();
56
+ }
57
+ createSession() {
58
+ return { sessionId: this.chatService.createSession() };
59
+ }
60
+ deleteSession(id) {
61
+ this.chatService.deleteSession(id);
62
+ }
63
+ };
64
+ exports.ChatController = ChatController;
65
+ __decorate([
66
+ (0, common_1.Post)(),
67
+ PublicChat(),
68
+ (0, common_1.HttpCode)(200),
69
+ (0, common_1.Header)('Content-Type', 'text/event-stream'),
70
+ (0, common_1.Header)('Cache-Control', 'no-cache'),
71
+ (0, common_1.Header)('Connection', 'keep-alive'),
72
+ (0, common_1.Header)('X-Accel-Buffering', 'no'),
73
+ __param(0, (0, common_1.Body)()),
74
+ __param(1, (0, common_1.Res)()),
75
+ __param(2, (0, common_1.Headers)('x-api-key')),
76
+ __metadata("design:type", Function),
77
+ __metadata("design:paramtypes", [Object, Object, String]),
78
+ __metadata("design:returntype", Promise)
79
+ ], ChatController.prototype, "chat", null);
80
+ __decorate([
81
+ (0, common_1.Post)('sessions'),
82
+ PublicChat(),
83
+ (0, common_1.HttpCode)(201),
84
+ __metadata("design:type", Function),
85
+ __metadata("design:paramtypes", []),
86
+ __metadata("design:returntype", Object)
87
+ ], ChatController.prototype, "createSession", null);
88
+ __decorate([
89
+ (0, common_1.Delete)('sessions/:id'),
90
+ PublicChat(),
91
+ (0, common_1.HttpCode)(204),
92
+ __param(0, (0, common_1.Param)('id')),
93
+ __metadata("design:type", Function),
94
+ __metadata("design:paramtypes", [String]),
95
+ __metadata("design:returntype", void 0)
96
+ ], ChatController.prototype, "deleteSession", null);
97
+ exports.ChatController = ChatController = __decorate([
98
+ (0, common_1.Controller)('v1/chat'),
99
+ PublicChat(),
100
+ (0, common_1.UseGuards)(rate_limit_guard_1.RateLimitGuard, api_key_guard_1.ApiKeyGuard),
101
+ __metadata("design:paramtypes", [chat_service_1.ChatService,
102
+ provider_factory_1.ProviderFactory])
103
+ ], ChatController);
104
+ //# sourceMappingURL=chat.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.controller.js","sourceRoot":"","sources":["../../src/chat/chat.controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { ChatStreamEvent } from '../types';
2
+ import { DefaultOrchestrator } from '../orchestrator/default.orchestrator';
3
+ import { SessionService } from '../session/session.service';
4
+ export interface ChatRequestContext {
5
+ apiKey?: string;
6
+ }
7
+ export declare class ChatService {
8
+ private readonly orchestrator;
9
+ private readonly sessionService;
10
+ constructor(orchestrator: DefaultOrchestrator, sessionService: SessionService);
11
+ chat(sessionToken: string | undefined, message: string, ctx?: ChatRequestContext): AsyncGenerator<ChatStreamEvent>;
12
+ createSession(): string;
13
+ deleteSession(token: string): void;
14
+ }
15
+ //# sourceMappingURL=chat.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.service.d.ts","sourceRoot":"","sources":["../../src/chat/chat.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sCAAsC,CAAC;AAChG,OAAO,EAA0C,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGpG,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBACa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBADd,YAAY,EAAE,mBAAmB,EACjC,cAAc,EAAE,cAAc;IAG1C,IAAI,CACT,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,OAAO,EAAE,MAAM,EACf,GAAG,GAAE,kBAAuB,GAC3B,cAAc,CAAC,eAAe,CAAC;IAoElC,aAAa,IAAI,MAAM;IAIvB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAGnC"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ChatService = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const default_orchestrator_1 = require("../orchestrator/default.orchestrator");
15
+ const session_service_1 = require("../session/session.service");
16
+ const error_sanitizer_1 = require("../utils/error-sanitizer");
17
+ let ChatService = class ChatService {
18
+ orchestrator;
19
+ sessionService;
20
+ constructor(orchestrator, sessionService) {
21
+ this.orchestrator = orchestrator;
22
+ this.sessionService = sessionService;
23
+ }
24
+ async *chat(sessionToken, message, ctx = {}) {
25
+ const token = sessionToken || this.sessionService.createSession();
26
+ const resolved = this.sessionService.resolveToken(token);
27
+ if (!resolved) {
28
+ yield {
29
+ type: 'error',
30
+ error: 'Invalid or expired session. Please start a new conversation.',
31
+ };
32
+ return;
33
+ }
34
+ const history = this.sessionService.getHistory(token);
35
+ try {
36
+ this.sessionService.addMessage(token, {
37
+ role: 'user',
38
+ content: message,
39
+ });
40
+ }
41
+ catch (err) {
42
+ if (err instanceof session_service_1.SessionLimitError) {
43
+ const sanitized = (0, error_sanitizer_1.sanitizeError)(err);
44
+ yield { type: 'error', error: sanitized.message };
45
+ return;
46
+ }
47
+ if (err instanceof session_service_1.InvalidSessionError) {
48
+ yield {
49
+ type: 'error',
50
+ error: 'Invalid or expired session. Please start a new conversation.',
51
+ };
52
+ return;
53
+ }
54
+ throw err;
55
+ }
56
+ const orchestratorCtx = {
57
+ apiKey: ctx.apiKey,
58
+ rawSessionId: resolved.rawId,
59
+ };
60
+ let fullResponse = '';
61
+ for await (const event of this.orchestrator.stream({
62
+ sessionId: resolved.rawId,
63
+ message,
64
+ history,
65
+ }, orchestratorCtx)) {
66
+ if (event.type === 'token' && event.content) {
67
+ fullResponse += event.content;
68
+ }
69
+ yield event;
70
+ }
71
+ if (fullResponse) {
72
+ try {
73
+ this.sessionService.addMessage(token, {
74
+ role: 'assistant',
75
+ content: fullResponse,
76
+ });
77
+ }
78
+ catch {
79
+ }
80
+ }
81
+ }
82
+ createSession() {
83
+ return this.sessionService.createSession();
84
+ }
85
+ deleteSession(token) {
86
+ this.sessionService.deleteSession(token);
87
+ }
88
+ };
89
+ exports.ChatService = ChatService;
90
+ exports.ChatService = ChatService = __decorate([
91
+ (0, common_1.Injectable)(),
92
+ __metadata("design:paramtypes", [default_orchestrator_1.DefaultOrchestrator,
93
+ session_service_1.SessionService])
94
+ ], ChatService);
95
+ //# sourceMappingURL=chat.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.service.js","sourceRoot":"","sources":["../../src/chat/chat.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAE5C,+EAAgG;AAChG,gEAAoG;AACpG,8DAAyD;AAOlD,IAAM,WAAW,GAAjB,MAAM,WAAW;IAEH;IACA;IAFnB,YACmB,YAAiC,EACjC,cAA8B;QAD9B,iBAAY,GAAZ,YAAY,CAAqB;QACjC,mBAAc,GAAd,cAAc,CAAgB;IAC9C,CAAC;IAEJ,KAAK,CAAC,CAAC,IAAI,CACT,YAAgC,EAChC,OAAe,EACf,MAA0B,EAAE;QAE5B,MAAM,KAAK,GAAG,YAAY,IAAI,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC;QAElE,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACzD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM;gBACJ,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,8DAA8D;aACtE,CAAC;YACF,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAEtD,IAAI,CAAC;YACH,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,EAAE;gBACpC,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,OAAO;aACjB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,mCAAiB,EAAE,CAAC;gBACrC,MAAM,SAAS,GAAG,IAAA,+BAAa,EAAC,GAAG,CAAC,CAAC;gBACrC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC;gBAClD,OAAO;YACT,CAAC;YACD,IAAI,GAAG,YAAY,qCAAmB,EAAE,CAAC;gBACvC,MAAM;oBACJ,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,8DAA8D;iBACtE,CAAC;gBACF,OAAO;YACT,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,MAAM,eAAe,GAAwB;YAC3C,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,YAAY,EAAE,QAAQ,CAAC,KAAK;SAC7B,CAAC;QAEF,IAAI,YAAY,GAAG,EAAE,CAAC;QAEtB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,CAChD;YACE,SAAS,EAAE,QAAQ,CAAC,KAAK;YACzB,OAAO;YACP,OAAO;SACR,EACD,eAAe,CAChB,EAAE,CAAC;YACF,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC5C,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC;YAChC,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QAED,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC;gBACH,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,EAAE;oBACpC,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,YAAY;iBACtB,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;YAET,CAAC;QACH,CAAC;IACH,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC;IAC7C,CAAC;IAED,aAAa,CAAC,KAAa;QACzB,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;CACF,CAAA;AArFY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAGsB,0CAAmB;QACjB,gCAAc;GAHtC,WAAW,CAqFvB"}
@@ -0,0 +1,8 @@
1
+ import { CanActivate, ExecutionContext } from '@nestjs/common';
2
+ import { AiChatModuleConfig } from '../types';
3
+ export declare class ApiKeyGuard implements CanActivate {
4
+ private readonly config;
5
+ constructor(config: AiChatModuleConfig);
6
+ canActivate(context: ExecutionContext): boolean;
7
+ }
8
+ //# sourceMappingURL=api-key.guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-key.guard.d.ts","sourceRoot":"","sources":["../../src/guards/api-key.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,gBAAgB,EAIjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAkB,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9D,qBACa,WAAY,YAAW,WAAW;IACT,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,kBAAkB;IAE/E,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO;CAkBhD"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ApiKeyGuard = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const types_1 = require("../types");
18
+ let ApiKeyGuard = class ApiKeyGuard {
19
+ config;
20
+ constructor(config) {
21
+ this.config = config;
22
+ }
23
+ canActivate(context) {
24
+ if (this.config.auth?.strategy !== 'api-key') {
25
+ return true;
26
+ }
27
+ const request = context.switchToHttp().getRequest();
28
+ const apiKey = request.headers['x-api-key'] || request.query?.apiKey;
29
+ if (!apiKey) {
30
+ throw new common_1.UnauthorizedException('Missing API key');
31
+ }
32
+ if (apiKey !== this.config.auth.key) {
33
+ throw new common_1.UnauthorizedException('Invalid API key');
34
+ }
35
+ return true;
36
+ }
37
+ };
38
+ exports.ApiKeyGuard = ApiKeyGuard;
39
+ exports.ApiKeyGuard = ApiKeyGuard = __decorate([
40
+ (0, common_1.Injectable)(),
41
+ __param(0, (0, common_1.Inject)(types_1.AI_CHAT_CONFIG)),
42
+ __metadata("design:paramtypes", [Object])
43
+ ], ApiKeyGuard);
44
+ //# sourceMappingURL=api-key.guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-key.guard.js","sourceRoot":"","sources":["../../src/guards/api-key.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAMwB;AACxB,oCAA8D;AAGvD,IAAM,WAAW,GAAjB,MAAM,WAAW;IAC+B;IAArD,YAAqD,MAA0B;QAA1B,WAAM,GAAN,MAAM,CAAoB;IAAG,CAAC;IAEnF,WAAW,CAAC,OAAyB;QACnC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;QAErE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,8BAAqB,CAAC,iBAAiB,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACpC,MAAM,IAAI,8BAAqB,CAAC,iBAAiB,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AArBY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;IAEE,WAAA,IAAA,eAAM,EAAC,sBAAc,CAAC,CAAA;;GADxB,WAAW,CAqBvB"}