@panguard-ai/core 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.
Files changed (233) hide show
  1. package/dist/adapters/adapter-registry.d.ts +150 -0
  2. package/dist/adapters/adapter-registry.d.ts.map +1 -0
  3. package/dist/adapters/adapter-registry.js +271 -0
  4. package/dist/adapters/adapter-registry.js.map +1 -0
  5. package/dist/adapters/base-adapter.d.ts +101 -0
  6. package/dist/adapters/base-adapter.d.ts.map +1 -0
  7. package/dist/adapters/base-adapter.js +160 -0
  8. package/dist/adapters/base-adapter.js.map +1 -0
  9. package/dist/adapters/defender-adapter.d.ts +90 -0
  10. package/dist/adapters/defender-adapter.d.ts.map +1 -0
  11. package/dist/adapters/defender-adapter.js +227 -0
  12. package/dist/adapters/defender-adapter.js.map +1 -0
  13. package/dist/adapters/index.d.ts +22 -0
  14. package/dist/adapters/index.d.ts.map +1 -0
  15. package/dist/adapters/index.js +23 -0
  16. package/dist/adapters/index.js.map +1 -0
  17. package/dist/adapters/syslog-adapter.d.ts +207 -0
  18. package/dist/adapters/syslog-adapter.d.ts.map +1 -0
  19. package/dist/adapters/syslog-adapter.js +432 -0
  20. package/dist/adapters/syslog-adapter.js.map +1 -0
  21. package/dist/adapters/types.d.ts +135 -0
  22. package/dist/adapters/types.d.ts.map +1 -0
  23. package/dist/adapters/types.js +13 -0
  24. package/dist/adapters/types.js.map +1 -0
  25. package/dist/adapters/wazuh-adapter.d.ts +120 -0
  26. package/dist/adapters/wazuh-adapter.d.ts.map +1 -0
  27. package/dist/adapters/wazuh-adapter.js +266 -0
  28. package/dist/adapters/wazuh-adapter.js.map +1 -0
  29. package/dist/ai/claude-provider.d.ts +66 -0
  30. package/dist/ai/claude-provider.d.ts.map +1 -0
  31. package/dist/ai/claude-provider.js +166 -0
  32. package/dist/ai/claude-provider.js.map +1 -0
  33. package/dist/ai/funnel-router.d.ts +75 -0
  34. package/dist/ai/funnel-router.d.ts.map +1 -0
  35. package/dist/ai/funnel-router.js +173 -0
  36. package/dist/ai/funnel-router.js.map +1 -0
  37. package/dist/ai/index.d.ts +77 -0
  38. package/dist/ai/index.d.ts.map +1 -0
  39. package/dist/ai/index.js +95 -0
  40. package/dist/ai/index.js.map +1 -0
  41. package/dist/ai/ollama-provider.d.ts +73 -0
  42. package/dist/ai/ollama-provider.d.ts.map +1 -0
  43. package/dist/ai/ollama-provider.js +200 -0
  44. package/dist/ai/ollama-provider.js.map +1 -0
  45. package/dist/ai/openai-provider.d.ts +70 -0
  46. package/dist/ai/openai-provider.d.ts.map +1 -0
  47. package/dist/ai/openai-provider.js +175 -0
  48. package/dist/ai/openai-provider.js.map +1 -0
  49. package/dist/ai/prompts/event-classifier.d.ts +25 -0
  50. package/dist/ai/prompts/event-classifier.d.ts.map +1 -0
  51. package/dist/ai/prompts/event-classifier.js +94 -0
  52. package/dist/ai/prompts/event-classifier.js.map +1 -0
  53. package/dist/ai/prompts/index.d.ts +13 -0
  54. package/dist/ai/prompts/index.d.ts.map +1 -0
  55. package/dist/ai/prompts/index.js +13 -0
  56. package/dist/ai/prompts/index.js.map +1 -0
  57. package/dist/ai/prompts/report-generator.d.ts +25 -0
  58. package/dist/ai/prompts/report-generator.d.ts.map +1 -0
  59. package/dist/ai/prompts/report-generator.js +131 -0
  60. package/dist/ai/prompts/report-generator.js.map +1 -0
  61. package/dist/ai/prompts/threat-analyzer.d.ts +26 -0
  62. package/dist/ai/prompts/threat-analyzer.d.ts.map +1 -0
  63. package/dist/ai/prompts/threat-analyzer.js +75 -0
  64. package/dist/ai/prompts/threat-analyzer.js.map +1 -0
  65. package/dist/ai/provider-base.d.ts +100 -0
  66. package/dist/ai/provider-base.d.ts.map +1 -0
  67. package/dist/ai/provider-base.js +166 -0
  68. package/dist/ai/provider-base.js.map +1 -0
  69. package/dist/ai/response-parser.d.ts +36 -0
  70. package/dist/ai/response-parser.d.ts.map +1 -0
  71. package/dist/ai/response-parser.js +195 -0
  72. package/dist/ai/response-parser.js.map +1 -0
  73. package/dist/ai/token-tracker.d.ts +72 -0
  74. package/dist/ai/token-tracker.d.ts.map +1 -0
  75. package/dist/ai/token-tracker.js +145 -0
  76. package/dist/ai/token-tracker.js.map +1 -0
  77. package/dist/ai/types.d.ts +138 -0
  78. package/dist/ai/types.d.ts.map +1 -0
  79. package/dist/ai/types.js +12 -0
  80. package/dist/ai/types.js.map +1 -0
  81. package/dist/cli/index.d.ts +146 -0
  82. package/dist/cli/index.d.ts.map +1 -0
  83. package/dist/cli/index.js +515 -0
  84. package/dist/cli/index.js.map +1 -0
  85. package/dist/cli/prompts.d.ts +58 -0
  86. package/dist/cli/prompts.d.ts.map +1 -0
  87. package/dist/cli/prompts.js +327 -0
  88. package/dist/cli/prompts.js.map +1 -0
  89. package/dist/cli/wizard.d.ts +58 -0
  90. package/dist/cli/wizard.d.ts.map +1 -0
  91. package/dist/cli/wizard.js +200 -0
  92. package/dist/cli/wizard.js.map +1 -0
  93. package/dist/discovery/firewall-checker.d.ts +28 -0
  94. package/dist/discovery/firewall-checker.d.ts.map +1 -0
  95. package/dist/discovery/firewall-checker.js +379 -0
  96. package/dist/discovery/firewall-checker.js.map +1 -0
  97. package/dist/discovery/index.d.ts +23 -0
  98. package/dist/discovery/index.d.ts.map +1 -0
  99. package/dist/discovery/index.js +29 -0
  100. package/dist/discovery/index.js.map +1 -0
  101. package/dist/discovery/network-scanner.d.ts +60 -0
  102. package/dist/discovery/network-scanner.d.ts.map +1 -0
  103. package/dist/discovery/network-scanner.js +640 -0
  104. package/dist/discovery/network-scanner.js.map +1 -0
  105. package/dist/discovery/os-detector.d.ts +24 -0
  106. package/dist/discovery/os-detector.d.ts.map +1 -0
  107. package/dist/discovery/os-detector.js +253 -0
  108. package/dist/discovery/os-detector.js.map +1 -0
  109. package/dist/discovery/osquery-provider.d.ts +127 -0
  110. package/dist/discovery/osquery-provider.d.ts.map +1 -0
  111. package/dist/discovery/osquery-provider.js +214 -0
  112. package/dist/discovery/osquery-provider.js.map +1 -0
  113. package/dist/discovery/risk-scorer.d.ts +66 -0
  114. package/dist/discovery/risk-scorer.d.ts.map +1 -0
  115. package/dist/discovery/risk-scorer.js +294 -0
  116. package/dist/discovery/risk-scorer.js.map +1 -0
  117. package/dist/discovery/security-tools.d.ts +31 -0
  118. package/dist/discovery/security-tools.d.ts.map +1 -0
  119. package/dist/discovery/security-tools.js +346 -0
  120. package/dist/discovery/security-tools.js.map +1 -0
  121. package/dist/discovery/service-detector.d.ts +28 -0
  122. package/dist/discovery/service-detector.d.ts.map +1 -0
  123. package/dist/discovery/service-detector.js +300 -0
  124. package/dist/discovery/service-detector.js.map +1 -0
  125. package/dist/discovery/types.d.ts +502 -0
  126. package/dist/discovery/types.d.ts.map +1 -0
  127. package/dist/discovery/types.js +12 -0
  128. package/dist/discovery/types.js.map +1 -0
  129. package/dist/discovery/user-auditor.d.ts +28 -0
  130. package/dist/discovery/user-auditor.d.ts.map +1 -0
  131. package/dist/discovery/user-auditor.js +385 -0
  132. package/dist/discovery/user-auditor.js.map +1 -0
  133. package/dist/i18n/config.d.ts +45 -0
  134. package/dist/i18n/config.d.ts.map +1 -0
  135. package/dist/i18n/config.js +135 -0
  136. package/dist/i18n/config.js.map +1 -0
  137. package/dist/i18n/index.d.ts +8 -0
  138. package/dist/i18n/index.d.ts.map +1 -0
  139. package/dist/i18n/index.js +8 -0
  140. package/dist/i18n/index.js.map +1 -0
  141. package/dist/index.d.ts +31 -0
  142. package/dist/index.d.ts.map +1 -0
  143. package/dist/index.js +31 -0
  144. package/dist/index.js.map +1 -0
  145. package/dist/monitor/event-normalizer.d.ts +102 -0
  146. package/dist/monitor/event-normalizer.d.ts.map +1 -0
  147. package/dist/monitor/event-normalizer.js +195 -0
  148. package/dist/monitor/event-normalizer.js.map +1 -0
  149. package/dist/monitor/file-monitor.d.ts +90 -0
  150. package/dist/monitor/file-monitor.d.ts.map +1 -0
  151. package/dist/monitor/file-monitor.js +222 -0
  152. package/dist/monitor/file-monitor.js.map +1 -0
  153. package/dist/monitor/index.d.ts +147 -0
  154. package/dist/monitor/index.d.ts.map +1 -0
  155. package/dist/monitor/index.js +293 -0
  156. package/dist/monitor/index.js.map +1 -0
  157. package/dist/monitor/log-monitor.d.ts +102 -0
  158. package/dist/monitor/log-monitor.d.ts.map +1 -0
  159. package/dist/monitor/log-monitor.js +245 -0
  160. package/dist/monitor/log-monitor.js.map +1 -0
  161. package/dist/monitor/network-monitor.d.ts +103 -0
  162. package/dist/monitor/network-monitor.d.ts.map +1 -0
  163. package/dist/monitor/network-monitor.js +336 -0
  164. package/dist/monitor/network-monitor.js.map +1 -0
  165. package/dist/monitor/process-monitor.d.ts +108 -0
  166. package/dist/monitor/process-monitor.d.ts.map +1 -0
  167. package/dist/monitor/process-monitor.js +245 -0
  168. package/dist/monitor/process-monitor.js.map +1 -0
  169. package/dist/monitor/threat-intel-feeds.d.ts +141 -0
  170. package/dist/monitor/threat-intel-feeds.d.ts.map +1 -0
  171. package/dist/monitor/threat-intel-feeds.js +430 -0
  172. package/dist/monitor/threat-intel-feeds.js.map +1 -0
  173. package/dist/monitor/threat-intel.d.ts +83 -0
  174. package/dist/monitor/threat-intel.d.ts.map +1 -0
  175. package/dist/monitor/threat-intel.js +215 -0
  176. package/dist/monitor/threat-intel.js.map +1 -0
  177. package/dist/monitor/types.d.ts +65 -0
  178. package/dist/monitor/types.d.ts.map +1 -0
  179. package/dist/monitor/types.js +20 -0
  180. package/dist/monitor/types.js.map +1 -0
  181. package/dist/rules/index.d.ts +115 -0
  182. package/dist/rules/index.d.ts.map +1 -0
  183. package/dist/rules/index.js +244 -0
  184. package/dist/rules/index.js.map +1 -0
  185. package/dist/rules/rule-loader.d.ts +54 -0
  186. package/dist/rules/rule-loader.d.ts.map +1 -0
  187. package/dist/rules/rule-loader.js +167 -0
  188. package/dist/rules/rule-loader.js.map +1 -0
  189. package/dist/rules/sigma-matcher.d.ts +40 -0
  190. package/dist/rules/sigma-matcher.d.ts.map +1 -0
  191. package/dist/rules/sigma-matcher.js +447 -0
  192. package/dist/rules/sigma-matcher.js.map +1 -0
  193. package/dist/rules/sigma-parser.d.ts +36 -0
  194. package/dist/rules/sigma-parser.d.ts.map +1 -0
  195. package/dist/rules/sigma-parser.js +180 -0
  196. package/dist/rules/sigma-parser.js.map +1 -0
  197. package/dist/rules/types.d.ts +112 -0
  198. package/dist/rules/types.d.ts.map +1 -0
  199. package/dist/rules/types.js +11 -0
  200. package/dist/rules/types.js.map +1 -0
  201. package/dist/rules/yara-scanner.d.ts +103 -0
  202. package/dist/rules/yara-scanner.d.ts.map +1 -0
  203. package/dist/rules/yara-scanner.js +421 -0
  204. package/dist/rules/yara-scanner.js.map +1 -0
  205. package/dist/scoring/achievements.d.ts +76 -0
  206. package/dist/scoring/achievements.d.ts.map +1 -0
  207. package/dist/scoring/achievements.js +211 -0
  208. package/dist/scoring/achievements.js.map +1 -0
  209. package/dist/scoring/index.d.ts +3 -0
  210. package/dist/scoring/index.d.ts.map +1 -0
  211. package/dist/scoring/index.js +3 -0
  212. package/dist/scoring/index.js.map +1 -0
  213. package/dist/scoring/security-score.d.ts +60 -0
  214. package/dist/scoring/security-score.d.ts.map +1 -0
  215. package/dist/scoring/security-score.js +211 -0
  216. package/dist/scoring/security-score.js.map +1 -0
  217. package/dist/types.d.ts +71 -0
  218. package/dist/types.d.ts.map +1 -0
  219. package/dist/types.js +8 -0
  220. package/dist/types.js.map +1 -0
  221. package/dist/utils/index.d.ts +10 -0
  222. package/dist/utils/index.d.ts.map +1 -0
  223. package/dist/utils/index.js +9 -0
  224. package/dist/utils/index.js.map +1 -0
  225. package/dist/utils/logger.d.ts +38 -0
  226. package/dist/utils/logger.d.ts.map +1 -0
  227. package/dist/utils/logger.js +71 -0
  228. package/dist/utils/logger.js.map +1 -0
  229. package/dist/utils/validation.d.ts +35 -0
  230. package/dist/utils/validation.d.ts.map +1 -0
  231. package/dist/utils/validation.js +56 -0
  232. package/dist/utils/validation.js.map +1 -0
  233. package/package.json +60 -0
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Claude (Anthropic) LLM provider implementation
3
+ * Claude (Anthropic) LLM 供應商實作
4
+ *
5
+ * Uses the @anthropic-ai/sdk package via dynamic import to avoid
6
+ * hard dependencies. Users must install the SDK separately.
7
+ * 透過動態匯入使用 @anthropic-ai/sdk 套件以避免硬性相依。
8
+ * 使用者必須另外安裝 SDK。
9
+ *
10
+ * @module @panguard-ai/core/ai/claude-provider
11
+ */
12
+ import { LLMProviderBase } from './provider-base.js';
13
+ /**
14
+ * Claude (Anthropic) LLM provider
15
+ * Claude (Anthropic) LLM 供應商
16
+ *
17
+ * Requires the @anthropic-ai/sdk package to be installed separately.
18
+ * The SDK is loaded via dynamic import() on first use.
19
+ * 需要另外安裝 @anthropic-ai/sdk 套件。
20
+ * SDK 在首次使用時透過動態 import() 載入。
21
+ */
22
+ export class ClaudeProvider extends LLMProviderBase {
23
+ /**
24
+ * Cached Anthropic client instance / 快取的 Anthropic 客戶端實例
25
+ * @internal
26
+ */
27
+ client = null;
28
+ /**
29
+ * Create a new ClaudeProvider instance
30
+ * 建立新的 ClaudeProvider 實例
31
+ *
32
+ * @param config - LLM configuration (apiKey required) / LLM 配置(需要 apiKey)
33
+ */
34
+ constructor(config) {
35
+ super(config);
36
+ this.logger.info('Claude provider initialized', { model: this.model });
37
+ }
38
+ /**
39
+ * Lazily initialize the Anthropic SDK client via dynamic import
40
+ * 透過動態匯入延遲初始化 Anthropic SDK 客戶端
41
+ *
42
+ * @returns Initialized Anthropic client / 初始化的 Anthropic 客戶端
43
+ * @throws Error if the SDK is not installed or API key is missing
44
+ * 如果 SDK 未安裝或 API 金鑰遺失則拋出錯誤
45
+ * @internal
46
+ */
47
+ async getClient() {
48
+ if (this.client) {
49
+ return this.client;
50
+ }
51
+ if (!this.config.apiKey) {
52
+ throw new Error('Claude API key is required. Set the apiKey field in LLMConfig or the ANTHROPIC_API_KEY environment variable.');
53
+ }
54
+ let Anthropic;
55
+ try {
56
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
57
+ const module = await import('@anthropic-ai/sdk');
58
+ Anthropic = (module['default'] ??
59
+ module['Anthropic'] ??
60
+ module);
61
+ }
62
+ catch (error) {
63
+ const message = error instanceof Error && error.message.includes('Cannot find')
64
+ ? 'Install @anthropic-ai/sdk to use Claude provider: npm install @anthropic-ai/sdk'
65
+ : `Failed to load @anthropic-ai/sdk: ${error instanceof Error ? error.message : String(error)}. ` +
66
+ 'Install it with: npm install @anthropic-ai/sdk';
67
+ throw new Error(message);
68
+ }
69
+ this.client = new Anthropic({
70
+ apiKey: this.config.apiKey,
71
+ timeout: this.config.timeout,
72
+ });
73
+ return this.client;
74
+ }
75
+ /**
76
+ * Check if the Claude API is available and the API key is valid
77
+ * 檢查 Claude API 是否可用且 API 金鑰有效
78
+ *
79
+ * Attempts to create a minimal message to verify connectivity.
80
+ * 嘗試建立最小訊息以驗證連接性。
81
+ *
82
+ * @returns True if Claude API is reachable / Claude API 可連接時回傳 true
83
+ */
84
+ async isAvailable() {
85
+ try {
86
+ if (!this.config.apiKey) {
87
+ this.logger.debug('Claude provider: no API key configured');
88
+ return false;
89
+ }
90
+ const client = await this.getClient();
91
+ // Send a minimal test request
92
+ // 發送最小測試請求
93
+ const response = await client.messages.create({
94
+ model: this.model,
95
+ max_tokens: 10,
96
+ messages: [{ role: 'user', content: 'Reply with "ok".' }],
97
+ });
98
+ const isOk = response.content.length > 0;
99
+ this.logger.debug('Claude availability check', { available: isOk });
100
+ return isOk;
101
+ }
102
+ catch (error) {
103
+ this.logger.debug('Claude not available', {
104
+ error: error instanceof Error ? error.message : String(error),
105
+ });
106
+ return false;
107
+ }
108
+ }
109
+ /**
110
+ * Send a prompt to the Claude API via the Anthropic SDK
111
+ * 透過 Anthropic SDK 向 Claude API 發送提示詞
112
+ *
113
+ * @param prompt - The prompt to send / 要發送的提示詞
114
+ * @returns Raw response text / 原始回應文字
115
+ * @throws Error if the API call fails / API 呼叫失敗時拋出錯誤
116
+ */
117
+ async sendRequest(prompt) {
118
+ const client = await this.getClient();
119
+ const systemMessage = this.config.lang === 'zh-TW'
120
+ ? '你是一位專業的資安分析師,專精於威脅偵測、事件分析和安全報告撰寫。請以繁體中文回應。'
121
+ : 'You are a professional cybersecurity analyst specializing in threat detection, incident analysis, and security report writing.';
122
+ try {
123
+ const response = await client.messages.create({
124
+ model: this.model,
125
+ max_tokens: this.config.maxTokens,
126
+ temperature: this.config.temperature,
127
+ system: systemMessage,
128
+ messages: [{ role: 'user', content: prompt }],
129
+ });
130
+ // Track token usage from API response
131
+ // 從 API 回應追蹤 Token 使用量
132
+ if (response.usage) {
133
+ this.tokenTracker.track(response.usage.input_tokens, response.usage.output_tokens);
134
+ }
135
+ // Extract text from content blocks
136
+ // 從內容區塊中提取文字
137
+ const textContent = response.content
138
+ .filter((block) => block.type === 'text')
139
+ .map((block) => block.text)
140
+ .join('\n');
141
+ this.logger.debug('Claude request completed', {
142
+ model: response.model,
143
+ inputTokens: response.usage?.input_tokens,
144
+ outputTokens: response.usage?.output_tokens,
145
+ });
146
+ return textContent;
147
+ }
148
+ catch (error) {
149
+ // Provide more specific error messages for common failures
150
+ // 為常見失敗提供更具體的錯誤訊息
151
+ if (error instanceof Error) {
152
+ if (error.message.includes('401') || error.message.includes('authentication')) {
153
+ throw new Error('Claude API authentication failed. Check your API key.');
154
+ }
155
+ if (error.message.includes('429') || error.message.includes('rate')) {
156
+ throw new Error('Claude API rate limit exceeded. Please wait and try again.');
157
+ }
158
+ if (error.message.includes('timeout') || error.message.includes('ETIMEDOUT')) {
159
+ throw new Error(`Claude API request timed out after ${this.config.timeout}ms.`);
160
+ }
161
+ }
162
+ throw error;
163
+ }
164
+ }
165
+ }
166
+ //# sourceMappingURL=claude-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-provider.js","sourceRoot":"","sources":["../../src/ai/claude-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Three-layer AI Funnel Router with automatic fallback
3
+ * 三層 AI 漏斗路由器(自動降級)
4
+ *
5
+ * Layer 1: Rules (always available) / 規則(永遠可用)
6
+ * Layer 2: Local AI via Ollama (server only) / 本地 AI(僅伺服器)
7
+ * Layer 3: Cloud AI via Claude/OpenAI / 雲端 AI
8
+ *
9
+ * Each layer catches failures and falls back to the next available layer.
10
+ * 每層捕捉失敗並降級到下一個可用層。
11
+ *
12
+ * @module @panguard-ai/core/ai/funnel-router
13
+ */
14
+ import type { LLMProvider, AnalysisResult } from './types.js';
15
+ /** Funnel layer status / 漏斗層狀態 */
16
+ export interface FunnelLayerStatus {
17
+ name: string;
18
+ available: boolean;
19
+ lastChecked: number;
20
+ failCount: number;
21
+ }
22
+ /** Funnel router configuration / 漏斗路由器配置 */
23
+ export interface FunnelRouterConfig {
24
+ /** Local AI provider (Ollama) / 本地 AI 供應商 */
25
+ localProvider?: LLMProvider;
26
+ /** Cloud AI provider (Claude/OpenAI) / 雲端 AI 供應商 */
27
+ cloudProvider?: LLMProvider;
28
+ /** Health check interval in ms (default: 60000) / 健康檢查間隔 */
29
+ healthCheckInterval?: number;
30
+ /** Max consecutive failures before disabling a layer / 連續失敗次數上限 */
31
+ maxFailures?: number;
32
+ }
33
+ /**
34
+ * Three-layer funnel router with automatic degradation
35
+ * 三層漏斗路由器(自動降級)
36
+ */
37
+ export declare class FunnelRouter {
38
+ private readonly localProvider;
39
+ private readonly cloudProvider;
40
+ private readonly maxFailures;
41
+ private localStatus;
42
+ private cloudStatus;
43
+ private healthTimer;
44
+ constructor(config: FunnelRouterConfig);
45
+ /**
46
+ * Start periodic health checks / 開始定期健康檢查
47
+ */
48
+ startHealthChecks(intervalMs?: number): void;
49
+ /**
50
+ * Stop health checks / 停止健康檢查
51
+ */
52
+ stopHealthChecks(): void;
53
+ /**
54
+ * Run health check on all providers / 對所有供應商執行健康檢查
55
+ */
56
+ checkHealth(): Promise<void>;
57
+ /**
58
+ * Analyze using the funnel: try local AI first, then cloud, then return null
59
+ * 使用漏斗分析:先嘗試本地 AI,然後雲端,最後回傳 null
60
+ *
61
+ * @param prompt - Analysis prompt / 分析提示詞
62
+ * @param context - Optional context / 可選上下文
63
+ * @returns Analysis result or null if all AI layers failed / 分析結果或 null
64
+ */
65
+ analyze(prompt: string, context?: string): Promise<AnalysisResult | null>;
66
+ /**
67
+ * Get current funnel status / 取得目前漏斗狀態
68
+ */
69
+ getStatus(): {
70
+ local: FunnelLayerStatus;
71
+ cloud: FunnelLayerStatus;
72
+ activeLayer: string;
73
+ };
74
+ }
75
+ //# sourceMappingURL=funnel-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"funnel-router.d.ts","sourceRoot":"","sources":["../../src/ai/funnel-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI9D,kCAAkC;AAClC,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,4CAA4C;AAC5C,MAAM,WAAW,kBAAkB;IACjC,6CAA6C;IAC7C,aAAa,CAAC,EAAE,WAAW,CAAC;IAC5B,oDAAoD;IACpD,aAAa,CAAC,EAAE,WAAW,CAAC;IAC5B,4DAA4D;IAC5D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IAErC,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,WAAW,CAA+C;gBAEtD,MAAM,EAAE,kBAAkB;IAyBtC;;OAEG;IACH,iBAAiB,CAAC,UAAU,SAAS,GAAG,IAAI;IAM5C;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAOxB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BlC;;;;;;;OAOG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAwD/E;;OAEG;IACH,SAAS,IAAI;QAAE,KAAK,EAAE,iBAAiB,CAAC;QAAC,KAAK,EAAE,iBAAiB,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE;CAczF"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Three-layer AI Funnel Router with automatic fallback
3
+ * 三層 AI 漏斗路由器(自動降級)
4
+ *
5
+ * Layer 1: Rules (always available) / 規則(永遠可用)
6
+ * Layer 2: Local AI via Ollama (server only) / 本地 AI(僅伺服器)
7
+ * Layer 3: Cloud AI via Claude/OpenAI / 雲端 AI
8
+ *
9
+ * Each layer catches failures and falls back to the next available layer.
10
+ * 每層捕捉失敗並降級到下一個可用層。
11
+ *
12
+ * @module @panguard-ai/core/ai/funnel-router
13
+ */
14
+ import { createLogger } from '../utils/logger.js';
15
+ const logger = createLogger('ai:funnel-router');
16
+ /**
17
+ * Three-layer funnel router with automatic degradation
18
+ * 三層漏斗路由器(自動降級)
19
+ */
20
+ export class FunnelRouter {
21
+ localProvider;
22
+ cloudProvider;
23
+ maxFailures;
24
+ localStatus;
25
+ cloudStatus;
26
+ healthTimer = null;
27
+ constructor(config) {
28
+ this.localProvider = config.localProvider ?? null;
29
+ this.cloudProvider = config.cloudProvider ?? null;
30
+ this.maxFailures = config.maxFailures ?? 3;
31
+ this.localStatus = {
32
+ name: 'local-ai',
33
+ available: !!this.localProvider,
34
+ lastChecked: 0,
35
+ failCount: 0,
36
+ };
37
+ this.cloudStatus = {
38
+ name: 'cloud-ai',
39
+ available: !!this.cloudProvider,
40
+ lastChecked: 0,
41
+ failCount: 0,
42
+ };
43
+ logger.info('FunnelRouter initialized', {
44
+ hasLocal: !!this.localProvider,
45
+ hasCloud: !!this.cloudProvider,
46
+ });
47
+ }
48
+ /**
49
+ * Start periodic health checks / 開始定期健康檢查
50
+ */
51
+ startHealthChecks(intervalMs = 60_000) {
52
+ if (this.healthTimer)
53
+ return;
54
+ this.healthTimer = setInterval(() => void this.checkHealth(), intervalMs);
55
+ void this.checkHealth();
56
+ }
57
+ /**
58
+ * Stop health checks / 停止健康檢查
59
+ */
60
+ stopHealthChecks() {
61
+ if (this.healthTimer) {
62
+ clearInterval(this.healthTimer);
63
+ this.healthTimer = null;
64
+ }
65
+ }
66
+ /**
67
+ * Run health check on all providers / 對所有供應商執行健康檢查
68
+ */
69
+ async checkHealth() {
70
+ const now = Date.now();
71
+ if (this.localProvider) {
72
+ try {
73
+ const ok = await this.localProvider.isAvailable();
74
+ this.localStatus.available = ok;
75
+ if (ok)
76
+ this.localStatus.failCount = 0;
77
+ }
78
+ catch {
79
+ this.localStatus.available = false;
80
+ }
81
+ this.localStatus.lastChecked = now;
82
+ }
83
+ if (this.cloudProvider) {
84
+ try {
85
+ const ok = await this.cloudProvider.isAvailable();
86
+ this.cloudStatus.available = ok;
87
+ if (ok)
88
+ this.cloudStatus.failCount = 0;
89
+ }
90
+ catch {
91
+ this.cloudStatus.available = false;
92
+ }
93
+ this.cloudStatus.lastChecked = now;
94
+ }
95
+ }
96
+ /**
97
+ * Analyze using the funnel: try local AI first, then cloud, then return null
98
+ * 使用漏斗分析:先嘗試本地 AI,然後雲端,最後回傳 null
99
+ *
100
+ * @param prompt - Analysis prompt / 分析提示詞
101
+ * @param context - Optional context / 可選上下文
102
+ * @returns Analysis result or null if all AI layers failed / 分析結果或 null
103
+ */
104
+ async analyze(prompt, context) {
105
+ // Layer 2: Try local AI (Ollama)
106
+ if (this.localProvider &&
107
+ this.localStatus.available &&
108
+ this.localStatus.failCount < this.maxFailures) {
109
+ try {
110
+ logger.debug('Attempting Layer 2 (local AI) analysis');
111
+ const result = await this.localProvider.analyze(prompt, context);
112
+ this.localStatus.failCount = 0;
113
+ logger.info('Layer 2 (local AI) analysis succeeded');
114
+ return result;
115
+ }
116
+ catch (err) {
117
+ this.localStatus.failCount++;
118
+ logger.warn('Layer 2 (local AI) failed, falling back', {
119
+ error: err instanceof Error ? err.message : String(err),
120
+ failCount: this.localStatus.failCount,
121
+ });
122
+ if (this.localStatus.failCount >= this.maxFailures) {
123
+ this.localStatus.available = false;
124
+ logger.error('Layer 2 (local AI) disabled after max failures');
125
+ }
126
+ }
127
+ }
128
+ // Layer 3: Try cloud AI (Claude/OpenAI)
129
+ if (this.cloudProvider &&
130
+ this.cloudStatus.available &&
131
+ this.cloudStatus.failCount < this.maxFailures) {
132
+ try {
133
+ logger.debug('Attempting Layer 3 (cloud AI) analysis');
134
+ const result = await this.cloudProvider.analyze(prompt, context);
135
+ this.cloudStatus.failCount = 0;
136
+ logger.info('Layer 3 (cloud AI) analysis succeeded');
137
+ return result;
138
+ }
139
+ catch (err) {
140
+ this.cloudStatus.failCount++;
141
+ logger.warn('Layer 3 (cloud AI) failed', {
142
+ error: err instanceof Error ? err.message : String(err),
143
+ failCount: this.cloudStatus.failCount,
144
+ });
145
+ if (this.cloudStatus.failCount >= this.maxFailures) {
146
+ this.cloudStatus.available = false;
147
+ logger.error('Layer 3 (cloud AI) disabled after max failures');
148
+ }
149
+ }
150
+ }
151
+ // All AI layers failed, return null (caller should use rules-only mode)
152
+ logger.warn('All AI layers unavailable, falling back to rules-only mode');
153
+ return null;
154
+ }
155
+ /**
156
+ * Get current funnel status / 取得目前漏斗狀態
157
+ */
158
+ getStatus() {
159
+ let activeLayer = 'rules-only';
160
+ if (this.localStatus.available && this.localStatus.failCount < this.maxFailures) {
161
+ activeLayer = 'local-ai';
162
+ }
163
+ else if (this.cloudStatus.available && this.cloudStatus.failCount < this.maxFailures) {
164
+ activeLayer = 'cloud-ai';
165
+ }
166
+ return {
167
+ local: { ...this.localStatus },
168
+ cloud: { ...this.cloudStatus },
169
+ activeLayer,
170
+ };
171
+ }
172
+ }
173
+ //# sourceMappingURL=funnel-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"funnel-router.js","sourceRoot":"","sources":["../../src/ai/funnel-router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * AI/LLM Unified Interface Layer
3
+ * AI/LLM 統一介面層
4
+ *
5
+ * Provides a unified interface for multiple LLM providers
6
+ * including Ollama (local), Claude API, and OpenAI API.
7
+ * Factory function `createLLM()` instantiates the appropriate provider
8
+ * based on configuration.
9
+ * 提供多個 LLM 供應商的統一介面,包括 Ollama(本地)、Claude API 和 OpenAI API。
10
+ * 工廠函式 `createLLM()` 根據配置實例化適當的供應商。
11
+ *
12
+ * @module @panguard-ai/core/ai
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { createLLM } from '@panguard-ai/core/ai';
17
+ *
18
+ * // Local Ollama provider (no API key needed)
19
+ * const ollama = createLLM({
20
+ * provider: 'ollama',
21
+ * model: 'llama3',
22
+ * lang: 'en',
23
+ * });
24
+ *
25
+ * // Claude provider (requires @anthropic-ai/sdk installed)
26
+ * const claude = createLLM({
27
+ * provider: 'claude',
28
+ * model: 'claude-sonnet-4-20250514',
29
+ * apiKey: process.env.ANTHROPIC_API_KEY,
30
+ * lang: 'zh-TW',
31
+ * });
32
+ *
33
+ * // Analyze a security threat
34
+ * const result = await ollama.analyze('Suspicious SSH brute force attempts detected');
35
+ * ```
36
+ */
37
+ import type { LLMConfig, LLMProvider } from './types.js';
38
+ /** AI module version / AI 模組版本 */
39
+ export declare const AI_VERSION = "0.1.0";
40
+ /**
41
+ * Create an LLM provider instance based on configuration
42
+ * 根據配置建立 LLM 供應商實例
43
+ *
44
+ * Factory function that instantiates the appropriate provider class
45
+ * based on the `provider` field in the config.
46
+ * 工廠函式,根據配置中的 `provider` 欄位實例化適當的供應商類別。
47
+ *
48
+ * @param config - LLM provider configuration / LLM 供應商配置
49
+ * @returns An LLMProvider instance / LLMProvider 實例
50
+ * @throws Error if the provider type is unknown / 供應商類型不明時拋出錯誤
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const provider = createLLM({
55
+ * provider: 'ollama',
56
+ * model: 'llama3',
57
+ * lang: 'en',
58
+ * });
59
+ *
60
+ * if (await provider.isAvailable()) {
61
+ * const analysis = await provider.analyze('Suspicious activity detected');
62
+ * console.log(analysis.summary);
63
+ * }
64
+ * ```
65
+ */
66
+ export declare function createLLM(config: LLMConfig): LLMProvider;
67
+ export type { LLMProviderType, LLMConfig, AnalysisResult, ThreatClassification, TokenUsage, LLMProvider, } from './types.js';
68
+ export { LLMProviderBase } from './provider-base.js';
69
+ export { OllamaProvider } from './ollama-provider.js';
70
+ export { ClaudeProvider } from './claude-provider.js';
71
+ export { OpenAIProvider } from './openai-provider.js';
72
+ export { TokenTracker } from './token-tracker.js';
73
+ export { FunnelRouter } from './funnel-router.js';
74
+ export type { FunnelRouterConfig, FunnelLayerStatus } from './funnel-router.js';
75
+ export { parseAnalysisResponse, parseClassificationResponse } from './response-parser.js';
76
+ export { getEventClassifierPrompt, getThreatAnalysisPrompt, getReportPrompt, } from './prompts/index.js';
77
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAKzD,kCAAkC;AAClC,eAAO,MAAM,UAAU,UAAU,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,WAAW,CAcxD;AAID,YAAY,EACV,eAAe,EACf,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAItD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAI1F,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,GAChB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * AI/LLM Unified Interface Layer
3
+ * AI/LLM 統一介面層
4
+ *
5
+ * Provides a unified interface for multiple LLM providers
6
+ * including Ollama (local), Claude API, and OpenAI API.
7
+ * Factory function `createLLM()` instantiates the appropriate provider
8
+ * based on configuration.
9
+ * 提供多個 LLM 供應商的統一介面,包括 Ollama(本地)、Claude API 和 OpenAI API。
10
+ * 工廠函式 `createLLM()` 根據配置實例化適當的供應商。
11
+ *
12
+ * @module @panguard-ai/core/ai
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { createLLM } from '@panguard-ai/core/ai';
17
+ *
18
+ * // Local Ollama provider (no API key needed)
19
+ * const ollama = createLLM({
20
+ * provider: 'ollama',
21
+ * model: 'llama3',
22
+ * lang: 'en',
23
+ * });
24
+ *
25
+ * // Claude provider (requires @anthropic-ai/sdk installed)
26
+ * const claude = createLLM({
27
+ * provider: 'claude',
28
+ * model: 'claude-sonnet-4-20250514',
29
+ * apiKey: process.env.ANTHROPIC_API_KEY,
30
+ * lang: 'zh-TW',
31
+ * });
32
+ *
33
+ * // Analyze a security threat
34
+ * const result = await ollama.analyze('Suspicious SSH brute force attempts detected');
35
+ * ```
36
+ */
37
+ import { OllamaProvider } from './ollama-provider.js';
38
+ import { ClaudeProvider } from './claude-provider.js';
39
+ import { OpenAIProvider } from './openai-provider.js';
40
+ /** AI module version / AI 模組版本 */
41
+ export const AI_VERSION = '0.1.0';
42
+ /**
43
+ * Create an LLM provider instance based on configuration
44
+ * 根據配置建立 LLM 供應商實例
45
+ *
46
+ * Factory function that instantiates the appropriate provider class
47
+ * based on the `provider` field in the config.
48
+ * 工廠函式,根據配置中的 `provider` 欄位實例化適當的供應商類別。
49
+ *
50
+ * @param config - LLM provider configuration / LLM 供應商配置
51
+ * @returns An LLMProvider instance / LLMProvider 實例
52
+ * @throws Error if the provider type is unknown / 供應商類型不明時拋出錯誤
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const provider = createLLM({
57
+ * provider: 'ollama',
58
+ * model: 'llama3',
59
+ * lang: 'en',
60
+ * });
61
+ *
62
+ * if (await provider.isAvailable()) {
63
+ * const analysis = await provider.analyze('Suspicious activity detected');
64
+ * console.log(analysis.summary);
65
+ * }
66
+ * ```
67
+ */
68
+ export function createLLM(config) {
69
+ switch (config.provider) {
70
+ case 'ollama':
71
+ return new OllamaProvider(config);
72
+ case 'claude':
73
+ return new ClaudeProvider(config);
74
+ case 'openai':
75
+ return new OpenAIProvider(config);
76
+ default:
77
+ throw new Error(`Unknown LLM provider: "${config.provider}". ` +
78
+ 'Supported providers: ollama, claude, openai');
79
+ }
80
+ }
81
+ // Re-export classes (for advanced usage / testing)
82
+ // 重新匯出類別(供進階使用 / 測試)
83
+ export { LLMProviderBase } from './provider-base.js';
84
+ export { OllamaProvider } from './ollama-provider.js';
85
+ export { ClaudeProvider } from './claude-provider.js';
86
+ export { OpenAIProvider } from './openai-provider.js';
87
+ // Re-export utilities
88
+ // 重新匯出工具
89
+ export { TokenTracker } from './token-tracker.js';
90
+ export { FunnelRouter } from './funnel-router.js';
91
+ export { parseAnalysisResponse, parseClassificationResponse } from './response-parser.js';
92
+ // Re-export prompts
93
+ // 重新匯出提示詞
94
+ export { getEventClassifierPrompt, getThreatAnalysisPrompt, getReportPrompt, } from './prompts/index.js';
95
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,kCAAkC;AAClC,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,SAAS,CAAC,MAAiB;IACzC,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,QAAQ;YACX,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;QACpC,KAAK,QAAQ;YACX,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;QACpC,KAAK,QAAQ;YACX,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;QACpC;YACE,MAAM,IAAI,KAAK,CACb,0BAA2B,MAAoB,CAAC,QAAQ,KAAK;gBAC3D,6CAA6C,CAChD,CAAC;IACN,CAAC;AACH,CAAC;AAaD,mDAAmD;AACnD,qBAAqB;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,sBAAsB;AACtB,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAE1F,oBAAoB;AACpB,UAAU;AACV,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,GAChB,MAAM,oBAAoB,CAAC"}