@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
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Panguard AI - Core Package
3
+ * Panguard 安全平台 - 核心套件
4
+ *
5
+ * Core shared modules for the Panguard AI platform.
6
+ * Provides types, i18n, utilities, discovery, monitoring, rules, AI, and adapters.
7
+ * 核心共用模組,提供類型、國際化、工具函式、偵察、監控、規則、AI 和對接器。
8
+ *
9
+ * @module @panguard-ai/core
10
+ */
11
+ // i18n / 國際化
12
+ export { initI18n, getI18n, changeLanguage, t, resetI18n } from './i18n/index.js';
13
+ // Utils / 工具函式
14
+ export { createLogger, setLogLevel, validateInput, sanitizeString, validateFilePath, } from './utils/index.js';
15
+ // Discovery engine / 偵察引擎
16
+ export { DISCOVERY_VERSION, detectOS, getNetworkInterfaces, scanOpenPorts, getActiveConnections, getGateway, getDnsServers, getDnsServersAsync, detectServices, detectSecurityTools, checkFirewall, auditUsers, calculateRiskScore, getRiskLevel, OsqueryProvider, createOsqueryProvider, } from './discovery/index.js';
17
+ // Rules engine / 規則引擎
18
+ export { RULES_VERSION, RuleEngine, parseSigmaYaml, parseSigmaFile, matchEvent, matchEventAgainstRules, loadRulesFromDirectory, watchRulesDirectory, YaraScanner, } from './rules/index.js';
19
+ // Monitor engine / 監控引擎
20
+ export { MONITOR_VERSION, MonitorEngine, LogMonitor, NetworkMonitor, ProcessMonitor, FileMonitor, checkThreatIntel, isPrivateIP, addThreatIntelEntry, getThreatIntelEntries, setFeedManager, getFeedManager, normalizeLogEvent, normalizeNetworkEvent, normalizeProcessEvent, normalizeFileEvent, DEFAULT_MONITOR_CONFIG, ThreatIntelFeedManager, } from './monitor/index.js';
21
+ // Scoring / 安全分數
22
+ export { calculateSecurityScore, scoreToGrade, scoreToColor, generateScoreSummary, AchievementTracker, ACHIEVEMENTS, } from './scoring/index.js';
23
+ // AI / LLM interface / AI/LLM 介面
24
+ export { AI_VERSION, createLLM } from './ai/index.js';
25
+ // Adapters / 對接器
26
+ export { ADAPTERS_VERSION, BaseAdapter, mapSeverity, mapEventSource, DefenderAdapter, WazuhAdapter, SyslogAdapter, parseSyslogMessage, AdapterRegistry, } from './adapters/index.js';
27
+ // CLI utilities / CLI 工具
28
+ export { c, colorSeverity, colorScore, colorGrade, Spinner, spinner, ProgressBar, progressBar, table, box, banner, header, symbols, divider, scoreDisplay, statusPanel, stripAnsi, formatDuration, timeAgo, visLen, promptSelect, promptText, promptConfirm, WizardEngine, } from './cli/index.js';
29
+ /** Core package version / 核心套件版本 */
30
+ export const CORE_VERSION = '0.1.0';
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,aAAa;AACb,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAElF,eAAe;AACf,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAG1B,0BAA0B;AAC1B,OAAO,EACL,iBAAiB,EACjB,QAAQ,EACR,oBAAoB,EACpB,aAAa,EACb,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAsB9B,sBAAsB;AACtB,OAAO,EACL,aAAa,EACb,UAAU,EACV,cAAc,EACd,cAAc,EACd,UAAU,EACV,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAW1B,wBAAwB;AACxB,OAAO,EACL,eAAe,EACf,aAAa,EACb,UAAU,EACV,cAAc,EACd,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAa5B,iBAAiB;AACjB,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAU5B,iCAAiC;AACjC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAStD,iBAAiB;AACjB,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAQ7B,yBAAyB;AACzB,OAAO,EACL,CAAC,EACD,aAAa,EACb,UAAU,EACV,UAAU,EACV,OAAO,EACP,OAAO,EACP,WAAW,EACX,WAAW,EACX,KAAK,EACL,GAAG,EACH,MAAM,EACN,MAAM,EACN,OAAO,EACP,OAAO,EACP,YAAY,EACZ,WAAW,EACX,SAAS,EACT,cAAc,EACd,OAAO,EACP,MAAM,EACN,YAAY,EACZ,UAAU,EACV,aAAa,EACb,YAAY,GACb,MAAM,gBAAgB,CAAC;AAcxB,oCAAoC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Event normalizer - converts raw events to SecurityEvent format
3
+ * 事件正規化器 - 將原始事件轉換為 SecurityEvent 格式
4
+ *
5
+ * @module @panguard-ai/core/monitor/event-normalizer
6
+ */
7
+ import type { SecurityEvent } from '../types.js';
8
+ /**
9
+ * Raw log event input
10
+ * 原始日誌事件輸入
11
+ */
12
+ interface RawLogEvent {
13
+ /** Log message / 日誌訊息 */
14
+ message: string;
15
+ /** Log source identifier / 日誌來源識別碼 */
16
+ source: string;
17
+ /** Event timestamp / 事件時間戳 */
18
+ timestamp?: Date;
19
+ }
20
+ /**
21
+ * Raw network connection input
22
+ * 原始網路連線輸入
23
+ */
24
+ interface RawNetworkConnection {
25
+ /** Local IP address / 本地 IP 位址 */
26
+ localAddr: string;
27
+ /** Local port / 本地埠號 */
28
+ localPort: number;
29
+ /** Remote IP address / 遠端 IP 位址 */
30
+ remoteAddr: string;
31
+ /** Remote port / 遠端埠號 */
32
+ remotePort: number;
33
+ /** Connection state / 連線狀態 */
34
+ state: string;
35
+ /** Associated process name / 關聯程序名稱 */
36
+ process?: string;
37
+ }
38
+ /**
39
+ * Raw process input
40
+ * 原始程序輸入
41
+ */
42
+ interface RawProcess {
43
+ /** Process ID / 程序 ID */
44
+ pid: number;
45
+ /** Process name / 程序名稱 */
46
+ name: string;
47
+ /** Executable path / 可執行檔路徑 */
48
+ path?: string;
49
+ /** User running the process / 執行程序的使用者 */
50
+ user?: string;
51
+ /** Full command line / 完整命令列 */
52
+ command?: string;
53
+ }
54
+ /**
55
+ * Raw file event input
56
+ * 原始檔案事件輸入
57
+ */
58
+ interface RawFileEvent {
59
+ /** File path / 檔案路徑 */
60
+ path: string;
61
+ /** Action performed / 執行的動作 */
62
+ action: 'modified' | 'created' | 'deleted';
63
+ /** Previous hash / 先前的雜湊 */
64
+ oldHash?: string;
65
+ /** New hash / 新的雜湊 */
66
+ newHash?: string;
67
+ }
68
+ /**
69
+ * Normalize a raw log event into a SecurityEvent
70
+ * 將原始日誌事件正規化為 SecurityEvent
71
+ *
72
+ * @param raw - Raw log event / 原始日誌事件
73
+ * @returns Normalized SecurityEvent / 正規化的 SecurityEvent
74
+ */
75
+ export declare function normalizeLogEvent(raw: RawLogEvent): SecurityEvent;
76
+ /**
77
+ * Normalize a network connection into a SecurityEvent
78
+ * 將網路連線正規化為 SecurityEvent
79
+ *
80
+ * @param connection - Raw network connection / 原始網路連線
81
+ * @returns Normalized SecurityEvent / 正規化的 SecurityEvent
82
+ */
83
+ export declare function normalizeNetworkEvent(connection: RawNetworkConnection): SecurityEvent;
84
+ /**
85
+ * Normalize a process event into a SecurityEvent
86
+ * 將程序事件正規化為 SecurityEvent
87
+ *
88
+ * @param process - Raw process info / 原始程序資訊
89
+ * @param action - Process action / 程序動作
90
+ * @returns Normalized SecurityEvent / 正規化的 SecurityEvent
91
+ */
92
+ export declare function normalizeProcessEvent(process: RawProcess, action: 'started' | 'stopped'): SecurityEvent;
93
+ /**
94
+ * Normalize a file event into a SecurityEvent
95
+ * 將檔案事件正規化為 SecurityEvent
96
+ *
97
+ * @param file - Raw file event / 原始檔案事件
98
+ * @returns Normalized SecurityEvent / 正規化的 SecurityEvent
99
+ */
100
+ export declare function normalizeFileEvent(file: RawFileEvent): SecurityEvent;
101
+ export {};
102
+ //# sourceMappingURL=event-normalizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-normalizer.d.ts","sourceRoot":"","sources":["../../src/monitor/event-normalizer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAyB,MAAM,aAAa,CAAC;AAExE;;;GAGG;AACH,UAAU,WAAW;IACnB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAED;;;GAGG;AACH,UAAU,oBAAoB;IAC5B,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,UAAU,UAAU;IAClB,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,UAAU,YAAY;IACpB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA8ED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,aAAa,CAcjE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,oBAAoB,GAAG,aAAa,CAqBrF;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,SAAS,GAAG,SAAS,GAC5B,aAAa,CAqBf;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,aAAa,CAiCpE"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Event normalizer - converts raw events to SecurityEvent format
3
+ * 事件正規化器 - 將原始事件轉換為 SecurityEvent 格式
4
+ *
5
+ * @module @panguard-ai/core/monitor/event-normalizer
6
+ */
7
+ import { randomUUID } from 'node:crypto';
8
+ import { hostname, platform } from 'node:os';
9
+ /** Current hostname cached / 快取的目前主機名稱 */
10
+ const currentHost = hostname();
11
+ /**
12
+ * Determine the EventSource based on the current platform
13
+ * 根據目前平台決定 EventSource
14
+ *
15
+ * @returns EventSource for the current OS / 目前作業系統的 EventSource
16
+ */
17
+ function getPlatformLogSource() {
18
+ const os = platform();
19
+ if (os === 'win32')
20
+ return 'windows_event';
21
+ return 'syslog';
22
+ }
23
+ /**
24
+ * Parse severity from log message content by matching keywords
25
+ * 通過匹配關鍵字從日誌訊息內容解析嚴重等級
26
+ *
27
+ * @param message - Log message to parse / 要解析的日誌訊息
28
+ * @returns Severity level / 嚴重等級
29
+ */
30
+ function parseSeverityFromMessage(message) {
31
+ const lower = message.toLowerCase();
32
+ if (lower.includes('critical') || lower.includes('emergency') || lower.includes('fatal')) {
33
+ return 'critical';
34
+ }
35
+ if (lower.includes('error') || lower.includes('fail') || lower.includes('denied')) {
36
+ return 'high';
37
+ }
38
+ if (lower.includes('warn') || lower.includes('warning') || lower.includes('suspicious')) {
39
+ return 'medium';
40
+ }
41
+ if (lower.includes('notice') || lower.includes('auth')) {
42
+ return 'low';
43
+ }
44
+ return 'info';
45
+ }
46
+ /**
47
+ * Extract a basic MITRE ATT&CK category from message patterns
48
+ * 從訊息模式中擷取基本的 MITRE ATT&CK 分類
49
+ *
50
+ * @param message - Log message / 日誌訊息
51
+ * @returns Category string / 分類字串
52
+ */
53
+ function extractCategoryFromMessage(message) {
54
+ const lower = message.toLowerCase();
55
+ if (lower.includes('login') ||
56
+ lower.includes('auth') ||
57
+ lower.includes('ssh') ||
58
+ lower.includes('logon')) {
59
+ return 'Initial Access';
60
+ }
61
+ if (lower.includes('sudo') || lower.includes('privilege') || lower.includes('elevation')) {
62
+ return 'Privilege Escalation';
63
+ }
64
+ if (lower.includes('firewall') || lower.includes('iptables') || lower.includes('blocked')) {
65
+ return 'Defense Evasion';
66
+ }
67
+ if (lower.includes('cron') || lower.includes('scheduled') || lower.includes('persistence')) {
68
+ return 'Persistence';
69
+ }
70
+ if (lower.includes('download') || lower.includes('curl') || lower.includes('wget')) {
71
+ return 'Command and Control';
72
+ }
73
+ if (lower.includes('exec') || lower.includes('spawn') || lower.includes('script')) {
74
+ return 'Execution';
75
+ }
76
+ return 'General';
77
+ }
78
+ /**
79
+ * Normalize a raw log event into a SecurityEvent
80
+ * 將原始日誌事件正規化為 SecurityEvent
81
+ *
82
+ * @param raw - Raw log event / 原始日誌事件
83
+ * @returns Normalized SecurityEvent / 正規化的 SecurityEvent
84
+ */
85
+ export function normalizeLogEvent(raw) {
86
+ return {
87
+ id: randomUUID(),
88
+ timestamp: raw.timestamp ?? new Date(),
89
+ source: getPlatformLogSource(),
90
+ severity: parseSeverityFromMessage(raw.message),
91
+ category: extractCategoryFromMessage(raw.message),
92
+ description: raw.message,
93
+ raw,
94
+ host: currentHost,
95
+ metadata: {
96
+ logSource: raw.source,
97
+ },
98
+ };
99
+ }
100
+ /**
101
+ * Normalize a network connection into a SecurityEvent
102
+ * 將網路連線正規化為 SecurityEvent
103
+ *
104
+ * @param connection - Raw network connection / 原始網路連線
105
+ * @returns Normalized SecurityEvent / 正規化的 SecurityEvent
106
+ */
107
+ export function normalizeNetworkEvent(connection) {
108
+ const description = `Network connection: ${connection.localAddr}:${connection.localPort} -> ${connection.remoteAddr}:${connection.remotePort} [${connection.state}]${connection.process ? ` (${connection.process})` : ''}`;
109
+ return {
110
+ id: randomUUID(),
111
+ timestamp: new Date(),
112
+ source: 'network',
113
+ severity: 'info',
114
+ category: 'Network Activity',
115
+ description,
116
+ raw: connection,
117
+ host: currentHost,
118
+ metadata: {
119
+ localAddr: connection.localAddr,
120
+ localPort: connection.localPort,
121
+ remoteAddr: connection.remoteAddr,
122
+ remotePort: connection.remotePort,
123
+ state: connection.state,
124
+ process: connection.process,
125
+ },
126
+ };
127
+ }
128
+ /**
129
+ * Normalize a process event into a SecurityEvent
130
+ * 將程序事件正規化為 SecurityEvent
131
+ *
132
+ * @param process - Raw process info / 原始程序資訊
133
+ * @param action - Process action / 程序動作
134
+ * @returns Normalized SecurityEvent / 正規化的 SecurityEvent
135
+ */
136
+ export function normalizeProcessEvent(process, action) {
137
+ const description = `Process ${action}: ${process.name} (PID: ${process.pid})${process.user ? ` by ${process.user}` : ''}`;
138
+ return {
139
+ id: randomUUID(),
140
+ timestamp: new Date(),
141
+ source: 'process',
142
+ severity: 'info',
143
+ category: action === 'started' ? 'Execution' : 'General',
144
+ description,
145
+ raw: { ...process, action },
146
+ host: currentHost,
147
+ metadata: {
148
+ pid: process.pid,
149
+ processName: process.name,
150
+ action,
151
+ path: process.path,
152
+ user: process.user,
153
+ command: process.command,
154
+ },
155
+ };
156
+ }
157
+ /**
158
+ * Normalize a file event into a SecurityEvent
159
+ * 將檔案事件正規化為 SecurityEvent
160
+ *
161
+ * @param file - Raw file event / 原始檔案事件
162
+ * @returns Normalized SecurityEvent / 正規化的 SecurityEvent
163
+ */
164
+ export function normalizeFileEvent(file) {
165
+ const actionLabels = {
166
+ modified: 'modified',
167
+ created: 'created',
168
+ deleted: 'deleted',
169
+ };
170
+ const description = `File ${actionLabels[file.action]}: ${file.path}`;
171
+ let severity = 'info';
172
+ if (file.action === 'modified' && file.oldHash && file.newHash && file.oldHash !== file.newHash) {
173
+ severity = 'medium';
174
+ }
175
+ if (file.action === 'deleted') {
176
+ severity = 'low';
177
+ }
178
+ return {
179
+ id: randomUUID(),
180
+ timestamp: new Date(),
181
+ source: 'file',
182
+ severity,
183
+ category: 'Defense Evasion',
184
+ description,
185
+ raw: file,
186
+ host: currentHost,
187
+ metadata: {
188
+ filePath: file.path,
189
+ action: file.action,
190
+ oldHash: file.oldHash,
191
+ newHash: file.newHash,
192
+ },
193
+ };
194
+ }
195
+ //# sourceMappingURL=event-normalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-normalizer.js","sourceRoot":"","sources":["../../src/monitor/event-normalizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * File integrity monitoring via hash comparison
3
+ * 透過雜湊比對進行檔案完整性監控
4
+ *
5
+ * Periodically computes SHA-256 hashes of watched files and detects
6
+ * creation, modification, and deletion events.
7
+ * 定期計算受監控檔案的 SHA-256 雜湊值,並偵測建立、修改和刪除事件。
8
+ *
9
+ * @module @panguard-ai/core/monitor/file-monitor
10
+ */
11
+ import { EventEmitter } from 'node:events';
12
+ import type { FileHashRecord } from './types.js';
13
+ /**
14
+ * FileMonitor - monitors file integrity by comparing SHA-256 hashes
15
+ * FileMonitor - 透過比較 SHA-256 雜湊值監控檔案完整性
16
+ *
17
+ * Events emitted:
18
+ * - 'file_changed': SecurityEvent - when a file hash changes / 當檔案雜湊值改變時
19
+ * - 'file_created': SecurityEvent - when a new file is detected / 當偵測到新檔案時
20
+ * - 'file_deleted': SecurityEvent - when a watched file is removed / 當受監控檔案被移除時
21
+ * - 'error': Error - when file checking encounters an error / 當檔案檢查遇到錯誤時
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const monitor = new FileMonitor(['/etc/passwd', '/etc/shadow'], 60000);
26
+ * monitor.on('file_changed', (event) => console.log('Changed:', event));
27
+ * monitor.start();
28
+ * ```
29
+ */
30
+ export declare class FileMonitor extends EventEmitter {
31
+ /** Whether the monitor is currently running / 監控器是否正在執行 */
32
+ private running;
33
+ /** Polling timer / 輪詢計時器 */
34
+ private timer?;
35
+ /** Stored file hash records / 儲存的檔案雜湊記錄 */
36
+ private fileHashes;
37
+ /** Paths to watch / 要監控的路徑 */
38
+ private watchPaths;
39
+ /** Polling interval in milliseconds / 輪詢間隔(毫秒) */
40
+ private pollInterval;
41
+ /**
42
+ * Create a new FileMonitor instance
43
+ * 建立新的 FileMonitor 實例
44
+ *
45
+ * @param watchPaths - Array of file paths to monitor / 要監控的檔案路徑陣列
46
+ * @param pollInterval - Polling interval in ms (default 60000) / 輪詢間隔毫秒數(預設 60000)
47
+ */
48
+ constructor(watchPaths: string[], pollInterval?: number);
49
+ /**
50
+ * Start monitoring file integrity
51
+ * 開始監控檔案完整性
52
+ */
53
+ start(): void;
54
+ /**
55
+ * Stop monitoring and clean up
56
+ * 停止監控並清理
57
+ */
58
+ stop(): void;
59
+ /**
60
+ * Check if the monitor is currently running
61
+ * 檢查監控器是否正在執行
62
+ *
63
+ * @returns True if running / 如果正在執行則為 true
64
+ */
65
+ isRunning(): boolean;
66
+ /**
67
+ * Compute the SHA-256 hash of a file
68
+ * 計算檔案的 SHA-256 雜湊值
69
+ *
70
+ * @param filePath - Path to the file / 檔案路徑
71
+ * @returns Hex-encoded SHA-256 hash / 十六進位編碼的 SHA-256 雜湊值
72
+ */
73
+ computeHash(filePath: string): Promise<string>;
74
+ /**
75
+ * Get the current file hash records
76
+ * 取得目前的檔案雜湊記錄
77
+ *
78
+ * @returns Map of file path to hash record / 檔案路徑到雜湊記錄的映射
79
+ */
80
+ getFileHashes(): ReadonlyMap<string, FileHashRecord>;
81
+ /**
82
+ * Check all watched files for changes
83
+ * 檢查所有受監控檔案的變更
84
+ *
85
+ * Compares current hashes with stored hashes and emits appropriate events.
86
+ * 比較目前雜湊值與儲存的雜湊值,並發出適當的事件。
87
+ */
88
+ private checkFiles;
89
+ }
90
+ //# sourceMappingURL=file-monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-monitor.d.ts","sourceRoot":"","sources":["../../src/monitor/file-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,WAAY,SAAQ,YAAY;IAC3C,2DAA2D;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,4BAA4B;IAC5B,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,2CAA2C;IAC3C,OAAO,CAAC,UAAU,CAA0C;IAC5D,8BAA8B;IAC9B,OAAO,CAAC,UAAU,CAAW;IAC7B,kDAAkD;IAClD,OAAO,CAAC,YAAY,CAAS;IAE7B;;;;;;OAMG;gBACS,UAAU,EAAE,MAAM,EAAE,EAAE,YAAY,SAAQ;IAMtD;;;OAGG;IACH,KAAK,IAAI,IAAI;IAmBb;;;OAGG;IACH,IAAI,IAAI,IAAI;IAeZ;;;;;OAKG;IACH,SAAS,IAAI,OAAO;IAIpB;;;;;;OAMG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKpD;;;;;OAKG;IACH,aAAa,IAAI,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC;IAIpD;;;;;;OAMG;YACW,UAAU;CA2GzB"}
@@ -0,0 +1,222 @@
1
+ /**
2
+ * File integrity monitoring via hash comparison
3
+ * 透過雜湊比對進行檔案完整性監控
4
+ *
5
+ * Periodically computes SHA-256 hashes of watched files and detects
6
+ * creation, modification, and deletion events.
7
+ * 定期計算受監控檔案的 SHA-256 雜湊值,並偵測建立、修改和刪除事件。
8
+ *
9
+ * @module @panguard-ai/core/monitor/file-monitor
10
+ */
11
+ import { EventEmitter } from 'node:events';
12
+ import { createHash } from 'node:crypto';
13
+ import { readFile, stat } from 'node:fs/promises';
14
+ import { createLogger } from '../utils/index.js';
15
+ import { normalizeFileEvent } from './event-normalizer.js';
16
+ const logger = createLogger('file-monitor');
17
+ /**
18
+ * FileMonitor - monitors file integrity by comparing SHA-256 hashes
19
+ * FileMonitor - 透過比較 SHA-256 雜湊值監控檔案完整性
20
+ *
21
+ * Events emitted:
22
+ * - 'file_changed': SecurityEvent - when a file hash changes / 當檔案雜湊值改變時
23
+ * - 'file_created': SecurityEvent - when a new file is detected / 當偵測到新檔案時
24
+ * - 'file_deleted': SecurityEvent - when a watched file is removed / 當受監控檔案被移除時
25
+ * - 'error': Error - when file checking encounters an error / 當檔案檢查遇到錯誤時
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const monitor = new FileMonitor(['/etc/passwd', '/etc/shadow'], 60000);
30
+ * monitor.on('file_changed', (event) => console.log('Changed:', event));
31
+ * monitor.start();
32
+ * ```
33
+ */
34
+ export class FileMonitor extends EventEmitter {
35
+ /** Whether the monitor is currently running / 監控器是否正在執行 */
36
+ running = false;
37
+ /** Polling timer / 輪詢計時器 */
38
+ timer;
39
+ /** Stored file hash records / 儲存的檔案雜湊記錄 */
40
+ fileHashes = new Map();
41
+ /** Paths to watch / 要監控的路徑 */
42
+ watchPaths;
43
+ /** Polling interval in milliseconds / 輪詢間隔(毫秒) */
44
+ pollInterval;
45
+ /**
46
+ * Create a new FileMonitor instance
47
+ * 建立新的 FileMonitor 實例
48
+ *
49
+ * @param watchPaths - Array of file paths to monitor / 要監控的檔案路徑陣列
50
+ * @param pollInterval - Polling interval in ms (default 60000) / 輪詢間隔毫秒數(預設 60000)
51
+ */
52
+ constructor(watchPaths, pollInterval = 60000) {
53
+ super();
54
+ this.watchPaths = watchPaths;
55
+ this.pollInterval = pollInterval;
56
+ }
57
+ /**
58
+ * Start monitoring file integrity
59
+ * 開始監控檔案完整性
60
+ */
61
+ start() {
62
+ if (this.running) {
63
+ logger.warn('FileMonitor is already running');
64
+ return;
65
+ }
66
+ this.running = true;
67
+ logger.info(`FileMonitor started (watching ${this.watchPaths.length} paths, poll interval: ${this.pollInterval}ms)`);
68
+ // Run an initial check immediately / 立即執行首次檢查
69
+ void this.checkFiles();
70
+ this.timer = setInterval(() => {
71
+ void this.checkFiles();
72
+ }, this.pollInterval);
73
+ }
74
+ /**
75
+ * Stop monitoring and clean up
76
+ * 停止監控並清理
77
+ */
78
+ stop() {
79
+ if (!this.running) {
80
+ logger.warn('FileMonitor is not running');
81
+ return;
82
+ }
83
+ if (this.timer) {
84
+ clearInterval(this.timer);
85
+ this.timer = undefined;
86
+ }
87
+ this.running = false;
88
+ logger.info('FileMonitor stopped');
89
+ }
90
+ /**
91
+ * Check if the monitor is currently running
92
+ * 檢查監控器是否正在執行
93
+ *
94
+ * @returns True if running / 如果正在執行則為 true
95
+ */
96
+ isRunning() {
97
+ return this.running;
98
+ }
99
+ /**
100
+ * Compute the SHA-256 hash of a file
101
+ * 計算檔案的 SHA-256 雜湊值
102
+ *
103
+ * @param filePath - Path to the file / 檔案路徑
104
+ * @returns Hex-encoded SHA-256 hash / 十六進位編碼的 SHA-256 雜湊值
105
+ */
106
+ async computeHash(filePath) {
107
+ const content = await readFile(filePath);
108
+ return createHash('sha256').update(content).digest('hex');
109
+ }
110
+ /**
111
+ * Get the current file hash records
112
+ * 取得目前的檔案雜湊記錄
113
+ *
114
+ * @returns Map of file path to hash record / 檔案路徑到雜湊記錄的映射
115
+ */
116
+ getFileHashes() {
117
+ return this.fileHashes;
118
+ }
119
+ /**
120
+ * Check all watched files for changes
121
+ * 檢查所有受監控檔案的變更
122
+ *
123
+ * Compares current hashes with stored hashes and emits appropriate events.
124
+ * 比較目前雜湊值與儲存的雜湊值,並發出適當的事件。
125
+ */
126
+ async checkFiles() {
127
+ const currentPaths = new Set();
128
+ for (const filePath of this.watchPaths) {
129
+ currentPaths.add(filePath);
130
+ try {
131
+ const fileStat = await stat(filePath);
132
+ const currentHash = await this.computeHash(filePath);
133
+ const now = new Date().toISOString();
134
+ const existingRecord = this.fileHashes.get(filePath);
135
+ if (!existingRecord) {
136
+ // New file detected (first check or newly created)
137
+ // 偵測到新檔案(首次檢查或新建立)
138
+ this.fileHashes.set(filePath, {
139
+ path: filePath,
140
+ hash: currentHash,
141
+ lastChecked: now,
142
+ size: fileStat.size,
143
+ });
144
+ // Only emit file_created if this is not the first run
145
+ // 僅在非首次執行時發出 file_created 事件
146
+ if (this.fileHashes.size >
147
+ this.watchPaths.length - (this.watchPaths.length - currentPaths.size)) {
148
+ // We check if we have seen at least one full cycle
149
+ // The first poll populates the baseline, subsequent polls detect changes
150
+ }
151
+ // Emit file_created for files discovered after initial baseline
152
+ // 為在初始基線之後發現的檔案發出 file_created
153
+ // On first run, we just store the baseline without emitting
154
+ // 首次執行時,我們只儲存基線而不發出事件
155
+ }
156
+ else if (existingRecord.hash !== currentHash) {
157
+ // File has been modified / 檔案已被修改
158
+ const oldHash = existingRecord.hash;
159
+ this.fileHashes.set(filePath, {
160
+ path: filePath,
161
+ hash: currentHash,
162
+ lastChecked: now,
163
+ size: fileStat.size,
164
+ });
165
+ const event = normalizeFileEvent({
166
+ path: filePath,
167
+ action: 'modified',
168
+ oldHash,
169
+ newHash: currentHash,
170
+ });
171
+ this.emit('file_changed', event);
172
+ logger.info(`File modified: ${filePath}`, {
173
+ oldHash: oldHash.substring(0, 12),
174
+ newHash: currentHash.substring(0, 12),
175
+ });
176
+ }
177
+ else {
178
+ // File unchanged, update last checked time
179
+ // 檔案未變更,更新最後檢查時間
180
+ existingRecord.lastChecked = now;
181
+ }
182
+ }
183
+ catch (err) {
184
+ const error = err;
185
+ if (error.code === 'ENOENT') {
186
+ // File does not exist / 檔案不存在
187
+ const existingRecord = this.fileHashes.get(filePath);
188
+ if (existingRecord) {
189
+ // File was previously tracked but now deleted
190
+ // 檔案先前被追蹤但現在已被刪除
191
+ this.fileHashes.delete(filePath);
192
+ const event = normalizeFileEvent({
193
+ path: filePath,
194
+ action: 'deleted',
195
+ oldHash: existingRecord.hash,
196
+ });
197
+ this.emit('file_deleted', event);
198
+ logger.info(`File deleted: ${filePath}`);
199
+ }
200
+ }
201
+ else {
202
+ logger.error(`Failed to check file: ${filePath}`, { error: String(err) });
203
+ this.emit('error', err instanceof Error ? err : new Error(String(err)));
204
+ }
205
+ }
206
+ }
207
+ // Check for files that were being tracked but are no longer in watchPaths
208
+ // 檢查先前被追蹤但不再在 watchPaths 中的檔案
209
+ for (const [trackedPath, record] of this.fileHashes) {
210
+ if (!currentPaths.has(trackedPath)) {
211
+ this.fileHashes.delete(trackedPath);
212
+ const event = normalizeFileEvent({
213
+ path: trackedPath,
214
+ action: 'deleted',
215
+ oldHash: record.hash,
216
+ });
217
+ this.emit('file_deleted', event);
218
+ }
219
+ }
220
+ }
221
+ }
222
+ //# sourceMappingURL=file-monitor.js.map