@coffeerunhobby/mcp-ha-connect 0.5.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 (294) hide show
  1. package/.dockerignore +8 -0
  2. package/.env.example +149 -0
  3. package/.gitattributes +30 -0
  4. package/Dockerfile +33 -0
  5. package/LICENSE +21 -0
  6. package/README.md +394 -0
  7. package/dist/config.d.ts +33 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +183 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/haClient/automations.d.ts +67 -0
  12. package/dist/haClient/automations.d.ts.map +1 -0
  13. package/dist/haClient/automations.js +181 -0
  14. package/dist/haClient/automations.js.map +1 -0
  15. package/dist/haClient/config.d.ts +28 -0
  16. package/dist/haClient/config.d.ts.map +1 -0
  17. package/dist/haClient/config.js +38 -0
  18. package/dist/haClient/config.js.map +1 -0
  19. package/dist/haClient/devices.d.ts +219 -0
  20. package/dist/haClient/devices.d.ts.map +1 -0
  21. package/dist/haClient/devices.js +506 -0
  22. package/dist/haClient/devices.js.map +1 -0
  23. package/dist/haClient/entities.d.ts +35 -0
  24. package/dist/haClient/entities.d.ts.map +1 -0
  25. package/dist/haClient/entities.js +97 -0
  26. package/dist/haClient/entities.js.map +1 -0
  27. package/dist/haClient/events.d.ts +138 -0
  28. package/dist/haClient/events.d.ts.map +1 -0
  29. package/dist/haClient/events.js +344 -0
  30. package/dist/haClient/events.js.map +1 -0
  31. package/dist/haClient/history.d.ts +26 -0
  32. package/dist/haClient/history.d.ts.map +1 -0
  33. package/dist/haClient/history.js +54 -0
  34. package/dist/haClient/history.js.map +1 -0
  35. package/dist/haClient/index.d.ts +153 -0
  36. package/dist/haClient/index.d.ts.map +1 -0
  37. package/dist/haClient/index.js +223 -0
  38. package/dist/haClient/index.js.map +1 -0
  39. package/dist/haClient/request.d.ts +34 -0
  40. package/dist/haClient/request.d.ts.map +1 -0
  41. package/dist/haClient/request.js +93 -0
  42. package/dist/haClient/request.js.map +1 -0
  43. package/dist/haClient/services.d.ts +22 -0
  44. package/dist/haClient/services.d.ts.map +1 -0
  45. package/dist/haClient/services.js +39 -0
  46. package/dist/haClient/services.js.map +1 -0
  47. package/dist/haClient/states.d.ts +26 -0
  48. package/dist/haClient/states.d.ts.map +1 -0
  49. package/dist/haClient/states.js +53 -0
  50. package/dist/haClient/states.js.map +1 -0
  51. package/dist/haClient/updates.d.ts +22 -0
  52. package/dist/haClient/updates.d.ts.map +1 -0
  53. package/dist/haClient/updates.js +48 -0
  54. package/dist/haClient/updates.js.map +1 -0
  55. package/dist/haClient.d.ts +97 -0
  56. package/dist/haClient.d.ts.map +1 -0
  57. package/dist/haClient.js +344 -0
  58. package/dist/haClient.js.map +1 -0
  59. package/dist/index.d.ts +8 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +92 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/localAI/index.d.ts +37 -0
  64. package/dist/localAI/index.d.ts.map +1 -0
  65. package/dist/localAI/index.js +73 -0
  66. package/dist/localAI/index.js.map +1 -0
  67. package/dist/localAI/prompts.d.ts +20 -0
  68. package/dist/localAI/prompts.d.ts.map +1 -0
  69. package/dist/localAI/prompts.js +48 -0
  70. package/dist/localAI/prompts.js.map +1 -0
  71. package/dist/localAI/providers/base.d.ts +51 -0
  72. package/dist/localAI/providers/base.d.ts.map +1 -0
  73. package/dist/localAI/providers/base.js +80 -0
  74. package/dist/localAI/providers/base.js.map +1 -0
  75. package/dist/localAI/providers/ollama.d.ts +22 -0
  76. package/dist/localAI/providers/ollama.d.ts.map +1 -0
  77. package/dist/localAI/providers/ollama.js +63 -0
  78. package/dist/localAI/providers/ollama.js.map +1 -0
  79. package/dist/localAI/providers/openai.d.ts +23 -0
  80. package/dist/localAI/providers/openai.d.ts.map +1 -0
  81. package/dist/localAI/providers/openai.js +63 -0
  82. package/dist/localAI/providers/openai.js.map +1 -0
  83. package/dist/localAI/types.d.ts +61 -0
  84. package/dist/localAI/types.d.ts.map +1 -0
  85. package/dist/localAI/types.js +6 -0
  86. package/dist/localAI/types.js.map +1 -0
  87. package/dist/ollamaClient.d.ts +37 -0
  88. package/dist/ollamaClient.d.ts.map +1 -0
  89. package/dist/ollamaClient.js +110 -0
  90. package/dist/ollamaClient.js.map +1 -0
  91. package/dist/resources/index.d.ts +11 -0
  92. package/dist/resources/index.d.ts.map +1 -0
  93. package/dist/resources/index.js +238 -0
  94. package/dist/resources/index.js.map +1 -0
  95. package/dist/server/common.d.ts +9 -0
  96. package/dist/server/common.d.ts.map +1 -0
  97. package/dist/server/common.js +27 -0
  98. package/dist/server/common.js.map +1 -0
  99. package/dist/server/eventSubscription.d.ts +53 -0
  100. package/dist/server/eventSubscription.d.ts.map +1 -0
  101. package/dist/server/eventSubscription.js +257 -0
  102. package/dist/server/eventSubscription.js.map +1 -0
  103. package/dist/server/http.d.ts +12 -0
  104. package/dist/server/http.d.ts.map +1 -0
  105. package/dist/server/http.js +491 -0
  106. package/dist/server/http.js.map +1 -0
  107. package/dist/server/rateLimiter.d.ts +70 -0
  108. package/dist/server/rateLimiter.d.ts.map +1 -0
  109. package/dist/server/rateLimiter.js +156 -0
  110. package/dist/server/rateLimiter.js.map +1 -0
  111. package/dist/server/sse.d.ts +32 -0
  112. package/dist/server/sse.d.ts.map +1 -0
  113. package/dist/server/sse.js +76 -0
  114. package/dist/server/sse.js.map +1 -0
  115. package/dist/server/stdio.d.ts +8 -0
  116. package/dist/server/stdio.d.ts.map +1 -0
  117. package/dist/server/stdio.js +16 -0
  118. package/dist/server/stdio.js.map +1 -0
  119. package/dist/server/stream.d.ts +26 -0
  120. package/dist/server/stream.d.ts.map +1 -0
  121. package/dist/server/stream.js +81 -0
  122. package/dist/server/stream.js.map +1 -0
  123. package/dist/server.d.ts +8 -0
  124. package/dist/server.d.ts.map +1 -0
  125. package/dist/server.js +30 -0
  126. package/dist/server.js.map +1 -0
  127. package/dist/tools/callService.d.ts +8 -0
  128. package/dist/tools/callService.d.ts.map +1 -0
  129. package/dist/tools/callService.js +100 -0
  130. package/dist/tools/callService.js.map +1 -0
  131. package/dist/tools/getClient.d.ts +8 -0
  132. package/dist/tools/getClient.d.ts.map +1 -0
  133. package/dist/tools/getClient.js +94 -0
  134. package/dist/tools/getClient.js.map +1 -0
  135. package/dist/tools/getDevice.d.ts +8 -0
  136. package/dist/tools/getDevice.d.ts.map +1 -0
  137. package/dist/tools/getDevice.js +94 -0
  138. package/dist/tools/getDevice.js.map +1 -0
  139. package/dist/tools/getEntitiesByDomain.d.ts +8 -0
  140. package/dist/tools/getEntitiesByDomain.d.ts.map +1 -0
  141. package/dist/tools/getEntitiesByDomain.js +80 -0
  142. package/dist/tools/getEntitiesByDomain.js.map +1 -0
  143. package/dist/tools/getState.d.ts +8 -0
  144. package/dist/tools/getState.d.ts.map +1 -0
  145. package/dist/tools/getState.js +90 -0
  146. package/dist/tools/getState.js.map +1 -0
  147. package/dist/tools/getStates.d.ts +8 -0
  148. package/dist/tools/getStates.d.ts.map +1 -0
  149. package/dist/tools/getStates.js +70 -0
  150. package/dist/tools/getStates.js.map +1 -0
  151. package/dist/tools/index.d.ts +9 -0
  152. package/dist/tools/index.d.ts.map +1 -0
  153. package/dist/tools/index.js +9 -0
  154. package/dist/tools/index.js.map +1 -0
  155. package/dist/tools/listClients.d.ts +8 -0
  156. package/dist/tools/listClients.d.ts.map +1 -0
  157. package/dist/tools/listClients.js +73 -0
  158. package/dist/tools/listClients.js.map +1 -0
  159. package/dist/tools/listDevices.d.ts +8 -0
  160. package/dist/tools/listDevices.d.ts.map +1 -0
  161. package/dist/tools/listDevices.js +73 -0
  162. package/dist/tools/listDevices.js.map +1 -0
  163. package/dist/tools/listSites.d.ts +8 -0
  164. package/dist/tools/listSites.d.ts.map +1 -0
  165. package/dist/tools/listSites.js +67 -0
  166. package/dist/tools/listSites.js.map +1 -0
  167. package/dist/tools/registry.d.ts +9 -0
  168. package/dist/tools/registry.d.ts.map +1 -0
  169. package/dist/tools/registry.js +1382 -0
  170. package/dist/tools/registry.js.map +1 -0
  171. package/dist/tools/searchDevices.d.ts +8 -0
  172. package/dist/tools/searchDevices.d.ts.map +1 -0
  173. package/dist/tools/searchDevices.js +84 -0
  174. package/dist/tools/searchDevices.js.map +1 -0
  175. package/dist/tools/searchEntities.d.ts +8 -0
  176. package/dist/tools/searchEntities.d.ts.map +1 -0
  177. package/dist/tools/searchEntities.js +80 -0
  178. package/dist/tools/searchEntities.js.map +1 -0
  179. package/dist/types/entity.d.ts +98 -0
  180. package/dist/types/entity.d.ts.map +1 -0
  181. package/dist/types/entity.js +2 -0
  182. package/dist/types/entity.js.map +1 -0
  183. package/dist/types/errors.d.ts +16 -0
  184. package/dist/types/errors.d.ts.map +1 -0
  185. package/dist/types/errors.js +32 -0
  186. package/dist/types/errors.js.map +1 -0
  187. package/dist/types/haConfig.d.ts +8 -0
  188. package/dist/types/haConfig.d.ts.map +1 -0
  189. package/dist/types/haConfig.js +2 -0
  190. package/dist/types/haConfig.js.map +1 -0
  191. package/dist/types/index.d.ts +6 -0
  192. package/dist/types/index.d.ts.map +1 -0
  193. package/dist/types/index.js +2 -0
  194. package/dist/types/index.js.map +1 -0
  195. package/dist/types/request.d.ts +7 -0
  196. package/dist/types/request.d.ts.map +1 -0
  197. package/dist/types/request.js +2 -0
  198. package/dist/types/request.js.map +1 -0
  199. package/dist/types/serviceCall.d.ts +18 -0
  200. package/dist/types/serviceCall.d.ts.map +1 -0
  201. package/dist/types/serviceCall.js +2 -0
  202. package/dist/types/serviceCall.js.map +1 -0
  203. package/dist/types.d.ts +2 -0
  204. package/dist/types.d.ts.map +1 -0
  205. package/dist/types.js +3 -0
  206. package/dist/types.js.map +1 -0
  207. package/dist/utils/config-validations.d.ts +12 -0
  208. package/dist/utils/config-validations.d.ts.map +1 -0
  209. package/dist/utils/config-validations.js +43 -0
  210. package/dist/utils/config-validations.js.map +1 -0
  211. package/dist/utils/logger.d.ts +24 -0
  212. package/dist/utils/logger.d.ts.map +1 -0
  213. package/dist/utils/logger.js +94 -0
  214. package/dist/utils/logger.js.map +1 -0
  215. package/dist/wrapper.d.ts +8 -0
  216. package/dist/wrapper.d.ts.map +1 -0
  217. package/dist/wrapper.js +301 -0
  218. package/dist/wrapper.js.map +1 -0
  219. package/docker-compose.yml +17 -0
  220. package/docs/CHANGELOG.md +86 -0
  221. package/docs/LOCAL_CLIENT.md +268 -0
  222. package/docs/SSE_API.md +341 -0
  223. package/eslint.config.js +33 -0
  224. package/n8n/ai-agent-safety-monitor.json +355 -0
  225. package/openapi.json +166 -0
  226. package/package.json +51 -0
  227. package/src/config.ts +260 -0
  228. package/src/haClient/automations.ts +217 -0
  229. package/src/haClient/config.ts +41 -0
  230. package/src/haClient/devices.ts +653 -0
  231. package/src/haClient/entities.ts +128 -0
  232. package/src/haClient/events.ts +456 -0
  233. package/src/haClient/history.ts +68 -0
  234. package/src/haClient/index.ts +287 -0
  235. package/src/haClient/request.ts +127 -0
  236. package/src/haClient/services.ts +45 -0
  237. package/src/haClient/states.ts +60 -0
  238. package/src/haClient/updates.ts +58 -0
  239. package/src/index.ts +99 -0
  240. package/src/localAI/index.ts +88 -0
  241. package/src/localAI/prompts.ts +50 -0
  242. package/src/localAI/providers/base.ts +120 -0
  243. package/src/localAI/providers/ollama.ts +78 -0
  244. package/src/localAI/providers/openai.ts +86 -0
  245. package/src/localAI/types.ts +67 -0
  246. package/src/resources/index.ts +266 -0
  247. package/src/server/common.ts +38 -0
  248. package/src/server/eventSubscription.ts +318 -0
  249. package/src/server/http.ts +546 -0
  250. package/src/server/rateLimiter.ts +195 -0
  251. package/src/server/sse.ts +120 -0
  252. package/src/server/stdio.ts +22 -0
  253. package/src/server/stream.ts +113 -0
  254. package/src/tools/callService.ts +114 -0
  255. package/src/tools/getEntitiesByDomain.ts +92 -0
  256. package/src/tools/getState.ts +103 -0
  257. package/src/tools/getStates.ts +80 -0
  258. package/src/tools/index.ts +9 -0
  259. package/src/tools/registry.ts +1521 -0
  260. package/src/tools/searchEntities.ts +92 -0
  261. package/src/types/entity.ts +110 -0
  262. package/src/types/errors.ts +33 -0
  263. package/src/types/haConfig.ts +7 -0
  264. package/src/types/index.ts +5 -0
  265. package/src/types/request.ts +6 -0
  266. package/src/types/serviceCall.ts +18 -0
  267. package/src/types.ts +2 -0
  268. package/src/utils/config-validations.ts +46 -0
  269. package/src/utils/logger.ts +114 -0
  270. package/src/wrapper.ts +340 -0
  271. package/tests/config.test.ts +332 -0
  272. package/tests/haClient/automations.test.ts +133 -0
  273. package/tests/haClient/config.test.ts +96 -0
  274. package/tests/haClient/entities.test.ts +188 -0
  275. package/tests/haClient/history.test.ts +170 -0
  276. package/tests/haClient/index.test.ts +221 -0
  277. package/tests/haClient/request.test.ts +217 -0
  278. package/tests/haClient/services.test.ts +120 -0
  279. package/tests/haClient/states.test.ts +119 -0
  280. package/tests/haClient/updates.test.ts +193 -0
  281. package/tests/index.test.ts +164 -0
  282. package/tests/localAI/index.test.ts +168 -0
  283. package/tests/localAI/ollama.test.ts +187 -0
  284. package/tests/localAI/openai.test.ts +257 -0
  285. package/tests/server/common.test.ts +64 -0
  286. package/tests/server/http.test.ts +326 -0
  287. package/tests/server/sse.test.ts +240 -0
  288. package/tests/server/stdio.test.ts +102 -0
  289. package/tests/server/stream.test.ts +287 -0
  290. package/tests/tools/registry.test.ts +355 -0
  291. package/tests/utils/config-validations.test.ts +289 -0
  292. package/tests/utils/logger.test.ts +327 -0
  293. package/tsconfig.json +25 -0
  294. package/vitest.config.ts +26 -0
package/dist/index.js ADDED
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Home Assistant MCP Server
4
+ * Entry point for the Model Context Protocol server
5
+ * Supports multiple transport modes: stdio, HTTP+SSE, HTTP+Stream
6
+ */
7
+ import { loadConfig } from './config.js';
8
+ import { HaClient } from './haClient/index.js';
9
+ import { LocalAIClient } from './localAI/index.js';
10
+ import { startHttpServer } from './server/http.js';
11
+ import { startStdioServer } from './server/stdio.js';
12
+ import { initLogger, logger } from './utils/logger.js';
13
+ async function main() {
14
+ try {
15
+ // Load and validate configuration
16
+ const config = loadConfig();
17
+ // When running in stdio mode, logs must go to stderr to avoid interfering with MCP protocol on stdout
18
+ const useStderr = !config.useHttp;
19
+ // Initialize logger with configured level, format, and output stream
20
+ initLogger(config.logLevel, config.logFormat, useStderr);
21
+ logger.info('Loaded Home Assistant configuration', {
22
+ baseUrl: config.baseUrl,
23
+ hasToken: !!config.token,
24
+ strictSsl: config.strictSsl,
25
+ timeout: config.timeout,
26
+ useHttp: config.useHttp,
27
+ httpTransport: config.useHttp ? config.httpTransport : undefined,
28
+ aiProvider: config.aiProvider,
29
+ aiUrl: config.aiUrl,
30
+ aiModel: config.aiModel,
31
+ });
32
+ // Create Home Assistant client
33
+ const client = new HaClient(config);
34
+ // Test Home Assistant connection
35
+ const apiCheck = await client.checkApi();
36
+ logger.info('Connected to Home Assistant', { message: apiCheck.message });
37
+ // Create Local AI client for AI analysis (unless explicitly disabled)
38
+ let aiClient;
39
+ if (config.aiProvider === 'none') {
40
+ logger.info('AI features disabled (AI_PROVIDER=none)');
41
+ }
42
+ else {
43
+ aiClient = new LocalAIClient(config);
44
+ const aiHealthy = await aiClient.checkHealth();
45
+ if (aiHealthy) {
46
+ logger.info('Connected to AI provider', {
47
+ provider: aiClient.getProviderName(),
48
+ url: config.aiUrl,
49
+ model: config.aiModel,
50
+ });
51
+ }
52
+ else {
53
+ logger.warn('AI provider not available - AI analysis tool will be disabled', {
54
+ provider: config.aiProvider,
55
+ url: config.aiUrl,
56
+ });
57
+ aiClient = undefined;
58
+ }
59
+ }
60
+ // Start server in appropriate mode
61
+ if (config.useHttp) {
62
+ await startHttpServer(client, config, aiClient);
63
+ }
64
+ else {
65
+ await startStdioServer(client, aiClient);
66
+ }
67
+ }
68
+ catch (error) {
69
+ const message = error instanceof Error ? error.message : String(error);
70
+ logger.error('Failed to start Home Assistant MCP server', {
71
+ error: message,
72
+ stack: error instanceof Error ? error.stack : undefined,
73
+ });
74
+ process.exitCode = 1;
75
+ }
76
+ }
77
+ // Handle graceful shutdown
78
+ process.on('SIGINT', () => {
79
+ logger.info('Received SIGINT, shutting down gracefully');
80
+ process.exit(0);
81
+ });
82
+ process.on('SIGTERM', () => {
83
+ logger.info('Received SIGTERM, shutting down gracefully');
84
+ process.exit(0);
85
+ });
86
+ // Start the server
87
+ main().catch((error) => {
88
+ const message = error instanceof Error ? error.message : String(error);
89
+ logger.error('Unhandled error in main', { error: message });
90
+ process.exitCode = 1;
91
+ });
92
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Local AI Client
3
+ * Factory and facade for AI providers
4
+ */
5
+ import type { EnvironmentConfig } from '../config.js';
6
+ import type { AIProviderConfig, AnalysisResult, SensorData } from './types.js';
7
+ export type { SensorData, AnalysisResult, AIProviderType } from './types.js';
8
+ /**
9
+ * Local AI Client
10
+ * Facade for AI analysis using configurable providers
11
+ */
12
+ export declare class LocalAIClient {
13
+ private provider;
14
+ private providerConfig;
15
+ constructor(config: EnvironmentConfig);
16
+ /**
17
+ * Analyze sensor data using AI
18
+ */
19
+ analyzeSensors(sensors: SensorData): Promise<AnalysisResult>;
20
+ /**
21
+ * Check if the AI provider is available
22
+ */
23
+ checkHealth(): Promise<boolean>;
24
+ /**
25
+ * Get the provider name
26
+ */
27
+ getProviderName(): string;
28
+ /**
29
+ * Get the configured model name
30
+ */
31
+ getModelName(): string;
32
+ /**
33
+ * Get the provider configuration
34
+ */
35
+ getConfig(): Readonly<AIProviderConfig>;
36
+ }
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/localAI/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAuB,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAKpG,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAe7E;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,cAAc,CAAmB;gBAE7B,MAAM,EAAE,iBAAiB;IAkBrC;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC;IAIlE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;OAEG;IACH,eAAe,IAAI,MAAM;IAIzB;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,gBAAgB,CAAC;CAGxC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Local AI Client
3
+ * Factory and facade for AI providers
4
+ */
5
+ import { logger } from '../utils/logger.js';
6
+ import { OllamaProvider } from './providers/ollama.js';
7
+ import { OpenAICompatibleProvider } from './providers/openai.js';
8
+ /**
9
+ * Create the appropriate AI provider based on configuration
10
+ */
11
+ function createProvider(providerConfig) {
12
+ switch (providerConfig.provider) {
13
+ case 'openai':
14
+ return new OpenAICompatibleProvider(providerConfig);
15
+ case 'ollama':
16
+ default:
17
+ return new OllamaProvider(providerConfig);
18
+ }
19
+ }
20
+ /**
21
+ * Local AI Client
22
+ * Facade for AI analysis using configurable providers
23
+ */
24
+ export class LocalAIClient {
25
+ provider;
26
+ providerConfig;
27
+ constructor(config) {
28
+ this.providerConfig = {
29
+ provider: config.aiProvider,
30
+ baseUrl: config.aiUrl,
31
+ model: config.aiModel,
32
+ timeout: config.aiTimeout,
33
+ apiKey: config.aiApiKey,
34
+ };
35
+ this.provider = createProvider(this.providerConfig);
36
+ logger.info('LocalAIClient initialized', {
37
+ provider: this.providerConfig.provider,
38
+ model: this.providerConfig.model,
39
+ url: this.providerConfig.baseUrl,
40
+ });
41
+ }
42
+ /**
43
+ * Analyze sensor data using AI
44
+ */
45
+ async analyzeSensors(sensors) {
46
+ return this.provider.analyzeSensors(sensors);
47
+ }
48
+ /**
49
+ * Check if the AI provider is available
50
+ */
51
+ async checkHealth() {
52
+ return this.provider.checkHealth();
53
+ }
54
+ /**
55
+ * Get the provider name
56
+ */
57
+ getProviderName() {
58
+ return this.provider.getProviderName();
59
+ }
60
+ /**
61
+ * Get the configured model name
62
+ */
63
+ getModelName() {
64
+ return this.providerConfig.model;
65
+ }
66
+ /**
67
+ * Get the provider configuration
68
+ */
69
+ getConfig() {
70
+ return { ...this.providerConfig };
71
+ }
72
+ }
73
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/localAI/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAKjE;;GAEG;AACH,SAAS,cAAc,CAAC,cAAgC;IACtD,QAAQ,cAAc,CAAC,QAAQ,EAAE,CAAC;QAChC,KAAK,QAAQ;YACX,OAAO,IAAI,wBAAwB,CAAC,cAAc,CAAC,CAAC;QACtD,KAAK,QAAQ,CAAC;QACd;YACE,OAAO,IAAI,cAAc,CAAC,cAAc,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,aAAa;IAChB,QAAQ,CAAsB;IAC9B,cAAc,CAAmB;IAEzC,YAAY,MAAyB;QACnC,IAAI,CAAC,cAAc,GAAG;YACpB,QAAQ,EAAE,MAAM,CAAC,UAAU;YAC3B,OAAO,EAAE,MAAM,CAAC,KAAK;YACrB,KAAK,EAAE,MAAM,CAAC,OAAO;YACrB,OAAO,EAAE,MAAM,CAAC,SAAS;YACzB,MAAM,EAAE,MAAM,CAAC,QAAQ;SACxB,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAEpD,MAAM,CAAC,IAAI,CAAC,2BAA2B,EAAE;YACvC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ;YACtC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK;YAChC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,OAAO;SACjC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,OAAmB;QACtC,OAAO,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW;QACf,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;IACpC,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * AI System Prompts
3
+ * Shared prompts for sensor analysis across all providers
4
+ */
5
+ /**
6
+ * System prompt for sensor analysis
7
+ */
8
+ export declare const SENSOR_ANALYSIS_SYSTEM_PROMPT = "You are a home automation AI analyzing Home Assistant sensors.\n\nSEVERITY RULES:\n- critical: Gas/smoke/CO detected, fire, temp>40\u00B0C indoors, power spike>500%, door open>2h with alarm\n- high: Battery<10%, power spike>300%, door open>30min with alarm, temp>35\u00B0C\n- medium: Battery<20%, connectivity issues, minor anomalies\n- low: Informational warnings\n\nOUTPUT FORMAT (JSON only, no markdown):\n{\n \"severity\": \"critical|high|medium|low\",\n \"issue\": \"brief description\",\n \"reasoning\": \"detailed explanation\",\n \"recommended_actions\": [\"action1\", \"action2\"],\n \"ssh_diagnostics\": [\"command1\", \"command2\"],\n \"confidence\": 0.85\n}\n\nRespond with JSON only. No extra text.";
9
+ /**
10
+ * Build the full prompt for sensor analysis
11
+ */
12
+ export declare function buildSensorAnalysisPrompt(sensors: Record<string, unknown>): string;
13
+ /**
14
+ * Build messages array for OpenAI-compatible APIs
15
+ */
16
+ export declare function buildChatMessages(sensors: Record<string, unknown>): Array<{
17
+ role: string;
18
+ content: string;
19
+ }>;
20
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/localAI/prompts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,eAAO,MAAM,6BAA6B,ktBAkBH,CAAC;AAExC;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAElF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAW5G"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * AI System Prompts
3
+ * Shared prompts for sensor analysis across all providers
4
+ */
5
+ /**
6
+ * System prompt for sensor analysis
7
+ */
8
+ export const SENSOR_ANALYSIS_SYSTEM_PROMPT = `You are a home automation AI analyzing Home Assistant sensors.
9
+
10
+ SEVERITY RULES:
11
+ - critical: Gas/smoke/CO detected, fire, temp>40°C indoors, power spike>500%, door open>2h with alarm
12
+ - high: Battery<10%, power spike>300%, door open>30min with alarm, temp>35°C
13
+ - medium: Battery<20%, connectivity issues, minor anomalies
14
+ - low: Informational warnings
15
+
16
+ OUTPUT FORMAT (JSON only, no markdown):
17
+ {
18
+ "severity": "critical|high|medium|low",
19
+ "issue": "brief description",
20
+ "reasoning": "detailed explanation",
21
+ "recommended_actions": ["action1", "action2"],
22
+ "ssh_diagnostics": ["command1", "command2"],
23
+ "confidence": 0.85
24
+ }
25
+
26
+ Respond with JSON only. No extra text.`;
27
+ /**
28
+ * Build the full prompt for sensor analysis
29
+ */
30
+ export function buildSensorAnalysisPrompt(sensors) {
31
+ return `${SENSOR_ANALYSIS_SYSTEM_PROMPT}\n\nAnalyze these sensors: ${JSON.stringify(sensors)}\n\nProvide JSON only:`;
32
+ }
33
+ /**
34
+ * Build messages array for OpenAI-compatible APIs
35
+ */
36
+ export function buildChatMessages(sensors) {
37
+ return [
38
+ {
39
+ role: 'system',
40
+ content: SENSOR_ANALYSIS_SYSTEM_PROMPT,
41
+ },
42
+ {
43
+ role: 'user',
44
+ content: `Analyze these sensors: ${JSON.stringify(sensors)}\n\nProvide JSON only:`,
45
+ },
46
+ ];
47
+ }
48
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/localAI/prompts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG;;;;;;;;;;;;;;;;;;uCAkBN,CAAC;AAExC;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAgC;IACxE,OAAO,GAAG,6BAA6B,8BAA8B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,wBAAwB,CAAC;AACvH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgC;IAChE,OAAO;QACL;YACE,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,6BAA6B;SACvC;QACD;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,0BAA0B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,wBAAwB;SACnF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Base AI Provider
3
+ * Abstract class with shared logic for all AI providers
4
+ */
5
+ import type { AIProviderConfig, AIProviderInterface, AnalysisResult, SensorData } from '../types.js';
6
+ /**
7
+ * Raw analysis result from AI (before adding metadata)
8
+ */
9
+ export interface RawAnalysisResult {
10
+ severity: 'critical' | 'high' | 'medium' | 'low';
11
+ issue: string;
12
+ reasoning: string;
13
+ recommended_actions: string[];
14
+ ssh_diagnostics: string[];
15
+ confidence: number;
16
+ }
17
+ /**
18
+ * Abstract base class for AI providers
19
+ */
20
+ export declare abstract class BaseAIProvider implements AIProviderInterface {
21
+ protected baseUrl: string;
22
+ protected model: string;
23
+ protected timeout: number;
24
+ protected apiKey?: string;
25
+ constructor(config: AIProviderConfig);
26
+ /**
27
+ * Get the provider name - must be implemented by subclasses
28
+ */
29
+ abstract getProviderName(): string;
30
+ /**
31
+ * Make the actual API request - must be implemented by subclasses
32
+ */
33
+ protected abstract makeRequest(sensors: SensorData): Promise<string>;
34
+ /**
35
+ * Check health - must be implemented by subclasses
36
+ */
37
+ abstract checkHealth(): Promise<boolean>;
38
+ /**
39
+ * Analyze sensors using AI
40
+ */
41
+ analyzeSensors(sensors: SensorData): Promise<AnalysisResult>;
42
+ /**
43
+ * Extract JSON from AI response text
44
+ */
45
+ protected extractJson(text: string): RawAnalysisResult;
46
+ /**
47
+ * Build authorization headers if API key is set
48
+ */
49
+ protected getAuthHeaders(): Record<string, string>;
50
+ }
51
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/localAI/providers/base.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErG;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,8BAAsB,cAAe,YAAW,mBAAmB;IACjE,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;gBAEd,MAAM,EAAE,gBAAgB;IAOpC;;OAEG;IACH,QAAQ,CAAC,eAAe,IAAI,MAAM;IAElC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAEpE;;OAEG;IACH,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAExC;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC;IA2ClE;;OAEG;IACH,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB;IAUtD;;OAEG;IACH,SAAS,CAAC,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAMnD"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Base AI Provider
3
+ * Abstract class with shared logic for all AI providers
4
+ */
5
+ import { logger } from '../../utils/logger.js';
6
+ /**
7
+ * Abstract base class for AI providers
8
+ */
9
+ export class BaseAIProvider {
10
+ baseUrl;
11
+ model;
12
+ timeout;
13
+ apiKey;
14
+ constructor(config) {
15
+ this.baseUrl = config.baseUrl;
16
+ this.model = config.model;
17
+ this.timeout = config.timeout;
18
+ this.apiKey = config.apiKey;
19
+ }
20
+ /**
21
+ * Analyze sensors using AI
22
+ */
23
+ async analyzeSensors(sensors) {
24
+ const sensorCount = Object.keys(sensors).length;
25
+ const providerName = this.getProviderName();
26
+ logger.info('Starting AI analysis', { sensorCount, model: this.model, provider: providerName });
27
+ const startTime = Date.now();
28
+ try {
29
+ const aiText = await this.makeRequest(sensors);
30
+ if (!aiText) {
31
+ throw new Error(`Empty response from ${providerName}`);
32
+ }
33
+ // Extract JSON from response (handles potential text around JSON)
34
+ const analysis = this.extractJson(aiText);
35
+ const elapsed = (Date.now() - startTime) / 1000;
36
+ logger.info('AI analysis complete', {
37
+ severity: analysis.severity,
38
+ elapsed: `${elapsed.toFixed(2)}s`,
39
+ model: this.model,
40
+ provider: providerName,
41
+ });
42
+ return {
43
+ ...analysis,
44
+ model: this.model,
45
+ provider: providerName,
46
+ response_time: parseFloat(elapsed.toFixed(2)),
47
+ };
48
+ }
49
+ catch (error) {
50
+ const elapsed = (Date.now() - startTime) / 1000;
51
+ logger.error('AI analysis failed', {
52
+ error: error instanceof Error ? error.message : String(error),
53
+ elapsed: `${elapsed.toFixed(2)}s`,
54
+ provider: providerName,
55
+ });
56
+ throw error;
57
+ }
58
+ }
59
+ /**
60
+ * Extract JSON from AI response text
61
+ */
62
+ extractJson(text) {
63
+ // Try to find JSON object in the response
64
+ const jsonMatch = text.match(/\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/);
65
+ if (!jsonMatch) {
66
+ throw new Error(`No JSON found in AI response: ${text.substring(0, 200)}`);
67
+ }
68
+ return JSON.parse(jsonMatch[0]);
69
+ }
70
+ /**
71
+ * Build authorization headers if API key is set
72
+ */
73
+ getAuthHeaders() {
74
+ if (this.apiKey) {
75
+ return { Authorization: `Bearer ${this.apiKey}` };
76
+ }
77
+ return {};
78
+ }
79
+ }
80
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/localAI/providers/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Ollama AI Provider
3
+ * Native Ollama API implementation
4
+ */
5
+ import type { AIProviderConfig, SensorData } from '../types.js';
6
+ import { BaseAIProvider } from './base.js';
7
+ /**
8
+ * Ollama AI provider using native Ollama API
9
+ */
10
+ export declare class OllamaProvider extends BaseAIProvider {
11
+ constructor(config: AIProviderConfig);
12
+ getProviderName(): string;
13
+ /**
14
+ * Make request to Ollama API
15
+ */
16
+ protected makeRequest(sensors: SensorData): Promise<string>;
17
+ /**
18
+ * Check if Ollama is available
19
+ */
20
+ checkHealth(): Promise<boolean>;
21
+ }
22
+ //# sourceMappingURL=ollama.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/localAI/providers/ollama.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAU3C;;GAEG;AACH,qBAAa,cAAe,SAAQ,cAAc;gBACpC,MAAM,EAAE,gBAAgB;IAIpC,eAAe,IAAI,MAAM;IAIzB;;OAEG;cACa,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IA+BjE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAWtC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Ollama AI Provider
3
+ * Native Ollama API implementation
4
+ */
5
+ import { buildSensorAnalysisPrompt } from '../prompts.js';
6
+ import { BaseAIProvider } from './base.js';
7
+ /**
8
+ * Ollama AI provider using native Ollama API
9
+ */
10
+ export class OllamaProvider extends BaseAIProvider {
11
+ constructor(config) {
12
+ super(config);
13
+ }
14
+ getProviderName() {
15
+ return 'ollama';
16
+ }
17
+ /**
18
+ * Make request to Ollama API
19
+ */
20
+ async makeRequest(sensors) {
21
+ const prompt = buildSensorAnalysisPrompt(sensors);
22
+ const response = await fetch(`${this.baseUrl}/api/generate`, {
23
+ method: 'POST',
24
+ headers: {
25
+ 'Content-Type': 'application/json',
26
+ ...this.getAuthHeaders(),
27
+ },
28
+ body: JSON.stringify({
29
+ model: this.model,
30
+ prompt,
31
+ stream: false,
32
+ options: {
33
+ temperature: 0.3,
34
+ num_predict: 2000,
35
+ num_ctx: 4096,
36
+ },
37
+ }),
38
+ signal: AbortSignal.timeout(this.timeout),
39
+ });
40
+ if (!response.ok) {
41
+ const errorText = await response.text();
42
+ throw new Error(`Ollama request failed: ${response.status} ${errorText}`);
43
+ }
44
+ const result = (await response.json());
45
+ return result.response ?? '';
46
+ }
47
+ /**
48
+ * Check if Ollama is available
49
+ */
50
+ async checkHealth() {
51
+ try {
52
+ const response = await fetch(`${this.baseUrl}/api/tags`, {
53
+ headers: this.getAuthHeaders(),
54
+ signal: AbortSignal.timeout(5000),
55
+ });
56
+ return response.ok;
57
+ }
58
+ catch {
59
+ return false;
60
+ }
61
+ }
62
+ }
63
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/localAI/providers/ollama.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAU3C;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,cAAc;IAChD,YAAY,MAAwB;QAClC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED,eAAe;QACb,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACO,KAAK,CAAC,WAAW,CAAC,OAAmB;QAC7C,MAAM,MAAM,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAElD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,eAAe,EAAE;YAC3D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,GAAG,IAAI,CAAC,cAAc,EAAE;aACzB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM;gBACN,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,WAAW,EAAE,GAAG;oBAChB,WAAW,EAAE,IAAI;oBACjB,OAAO,EAAE,IAAI;iBACd;aACF,CAAC;YACF,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;SAC1C,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmB,CAAC;QACzD,OAAO,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,WAAW,EAAE;gBACvD,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE;gBAC9B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;aAClC,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC,EAAE,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * OpenAI-Compatible AI Provider
3
+ * Works with LocalAI, LM Studio, vLLM, and any OpenAI-compatible API
4
+ */
5
+ import type { AIProviderConfig, SensorData } from '../types.js';
6
+ import { BaseAIProvider } from './base.js';
7
+ /**
8
+ * OpenAI-compatible AI provider
9
+ * Works with LocalAI, LM Studio, vLLM, and other OpenAI-compatible APIs
10
+ */
11
+ export declare class OpenAICompatibleProvider extends BaseAIProvider {
12
+ constructor(config: AIProviderConfig);
13
+ getProviderName(): string;
14
+ /**
15
+ * Make request to OpenAI-compatible API
16
+ */
17
+ protected makeRequest(sensors: SensorData): Promise<string>;
18
+ /**
19
+ * Check if the OpenAI-compatible API is available
20
+ */
21
+ checkHealth(): Promise<boolean>;
22
+ }
23
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/localAI/providers/openai.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAgB3C;;;GAGG;AACH,qBAAa,wBAAyB,SAAQ,cAAc;gBAC9C,MAAM,EAAE,gBAAgB;IAIpC,eAAe,IAAI,MAAM;IAIzB;;OAEG;cACa,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAgCjE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAWtC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * OpenAI-Compatible AI Provider
3
+ * Works with LocalAI, LM Studio, vLLM, and any OpenAI-compatible API
4
+ */
5
+ import { buildChatMessages } from '../prompts.js';
6
+ import { BaseAIProvider } from './base.js';
7
+ /**
8
+ * OpenAI-compatible AI provider
9
+ * Works with LocalAI, LM Studio, vLLM, and other OpenAI-compatible APIs
10
+ */
11
+ export class OpenAICompatibleProvider extends BaseAIProvider {
12
+ constructor(config) {
13
+ super(config);
14
+ }
15
+ getProviderName() {
16
+ return 'openai-compatible';
17
+ }
18
+ /**
19
+ * Make request to OpenAI-compatible API
20
+ */
21
+ async makeRequest(sensors) {
22
+ const messages = buildChatMessages(sensors);
23
+ const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {
24
+ method: 'POST',
25
+ headers: {
26
+ 'Content-Type': 'application/json',
27
+ ...this.getAuthHeaders(),
28
+ },
29
+ body: JSON.stringify({
30
+ model: this.model,
31
+ messages,
32
+ temperature: 0.3,
33
+ max_tokens: 2000,
34
+ }),
35
+ signal: AbortSignal.timeout(this.timeout),
36
+ });
37
+ if (!response.ok) {
38
+ const errorText = await response.text();
39
+ throw new Error(`OpenAI-compatible API request failed: ${response.status} ${errorText}`);
40
+ }
41
+ const result = (await response.json());
42
+ if (result.error) {
43
+ throw new Error(`API error: ${result.error.message}`);
44
+ }
45
+ return result.choices?.[0]?.message?.content ?? '';
46
+ }
47
+ /**
48
+ * Check if the OpenAI-compatible API is available
49
+ */
50
+ async checkHealth() {
51
+ try {
52
+ const response = await fetch(`${this.baseUrl}/v1/models`, {
53
+ headers: this.getAuthHeaders(),
54
+ signal: AbortSignal.timeout(5000),
55
+ });
56
+ return response.ok;
57
+ }
58
+ catch {
59
+ return false;
60
+ }
61
+ }
62
+ }
63
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/localAI/providers/openai.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAgB3C;;;GAGG;AACH,MAAM,OAAO,wBAAyB,SAAQ,cAAc;IAC1D,YAAY,MAAwB;QAClC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED,eAAe;QACb,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IAED;;OAEG;IACO,KAAK,CAAC,WAAW,CAAC,OAAmB;QAC7C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAE5C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,sBAAsB,EAAE;YAClE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,GAAG,IAAI,CAAC,cAAc,EAAE;aACzB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,QAAQ;gBACR,WAAW,EAAE,GAAG;gBAChB,UAAU,EAAE,IAAI;aACjB,CAAC;YACF,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;SAC1C,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,yCAAyC,QAAQ,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;QAC3F,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuB,CAAC;QAE7D,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,YAAY,EAAE;gBACxD,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE;gBAC9B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;aAClC,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC,EAAE,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}