@superdangerous/app-framework 4.9.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 (239) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +652 -0
  3. package/dist/api/logsRouter.d.ts +20 -0
  4. package/dist/api/logsRouter.d.ts.map +1 -0
  5. package/dist/api/logsRouter.js +515 -0
  6. package/dist/api/logsRouter.js.map +1 -0
  7. package/dist/cli/dev-server.d.ts +7 -0
  8. package/dist/cli/dev-server.d.ts.map +1 -0
  9. package/dist/cli/dev-server.js +640 -0
  10. package/dist/cli/dev-server.js.map +1 -0
  11. package/dist/cli/index.d.ts +7 -0
  12. package/dist/cli/index.d.ts.map +1 -0
  13. package/dist/cli/index.js +26 -0
  14. package/dist/cli/index.js.map +1 -0
  15. package/dist/core/StandardServer.d.ts +129 -0
  16. package/dist/core/StandardServer.d.ts.map +1 -0
  17. package/dist/core/StandardServer.js +453 -0
  18. package/dist/core/StandardServer.js.map +1 -0
  19. package/dist/core/apiResponse.d.ts +69 -0
  20. package/dist/core/apiResponse.d.ts.map +1 -0
  21. package/dist/core/apiResponse.js +127 -0
  22. package/dist/core/apiResponse.js.map +1 -0
  23. package/dist/core/healthCheck.d.ts +160 -0
  24. package/dist/core/healthCheck.d.ts.map +1 -0
  25. package/dist/core/healthCheck.js +398 -0
  26. package/dist/core/healthCheck.js.map +1 -0
  27. package/dist/core/index.d.ts +40 -0
  28. package/dist/core/index.d.ts.map +1 -0
  29. package/dist/core/index.js +40 -0
  30. package/dist/core/index.js.map +1 -0
  31. package/dist/core/logger.d.ts +117 -0
  32. package/dist/core/logger.d.ts.map +1 -0
  33. package/dist/core/logger.js +826 -0
  34. package/dist/core/logger.js.map +1 -0
  35. package/dist/core/portUtils.d.ts +71 -0
  36. package/dist/core/portUtils.d.ts.map +1 -0
  37. package/dist/core/portUtils.js +240 -0
  38. package/dist/core/portUtils.js.map +1 -0
  39. package/dist/core/storageService.d.ts +119 -0
  40. package/dist/core/storageService.d.ts.map +1 -0
  41. package/dist/core/storageService.js +405 -0
  42. package/dist/core/storageService.js.map +1 -0
  43. package/dist/desktop/bundler.d.ts +40 -0
  44. package/dist/desktop/bundler.d.ts.map +1 -0
  45. package/dist/desktop/bundler.js +176 -0
  46. package/dist/desktop/bundler.js.map +1 -0
  47. package/dist/desktop/index.d.ts +25 -0
  48. package/dist/desktop/index.d.ts.map +1 -0
  49. package/dist/desktop/index.js +15 -0
  50. package/dist/desktop/index.js.map +1 -0
  51. package/dist/desktop/native-modules.d.ts +66 -0
  52. package/dist/desktop/native-modules.d.ts.map +1 -0
  53. package/dist/desktop/native-modules.js +200 -0
  54. package/dist/desktop/native-modules.js.map +1 -0
  55. package/dist/index.d.ts +29 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +39 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/logging/LogCategories.d.ts +87 -0
  60. package/dist/logging/LogCategories.d.ts.map +1 -0
  61. package/dist/logging/LogCategories.js +205 -0
  62. package/dist/logging/LogCategories.js.map +1 -0
  63. package/dist/middleware/aiErrorHandler.d.ts +31 -0
  64. package/dist/middleware/aiErrorHandler.d.ts.map +1 -0
  65. package/dist/middleware/aiErrorHandler.js +181 -0
  66. package/dist/middleware/aiErrorHandler.js.map +1 -0
  67. package/dist/middleware/auth.d.ts +101 -0
  68. package/dist/middleware/auth.d.ts.map +1 -0
  69. package/dist/middleware/auth.js +230 -0
  70. package/dist/middleware/auth.js.map +1 -0
  71. package/dist/middleware/cors.d.ts +56 -0
  72. package/dist/middleware/cors.d.ts.map +1 -0
  73. package/dist/middleware/cors.js +123 -0
  74. package/dist/middleware/cors.js.map +1 -0
  75. package/dist/middleware/errorHandler.d.ts +13 -0
  76. package/dist/middleware/errorHandler.d.ts.map +1 -0
  77. package/dist/middleware/errorHandler.js +85 -0
  78. package/dist/middleware/errorHandler.js.map +1 -0
  79. package/dist/middleware/fileUpload.d.ts +62 -0
  80. package/dist/middleware/fileUpload.d.ts.map +1 -0
  81. package/dist/middleware/fileUpload.js +175 -0
  82. package/dist/middleware/fileUpload.js.map +1 -0
  83. package/dist/middleware/health.d.ts +48 -0
  84. package/dist/middleware/health.d.ts.map +1 -0
  85. package/dist/middleware/health.js +143 -0
  86. package/dist/middleware/health.js.map +1 -0
  87. package/dist/middleware/index.d.ts +20 -0
  88. package/dist/middleware/index.d.ts.map +1 -0
  89. package/dist/middleware/index.js +18 -0
  90. package/dist/middleware/index.js.map +1 -0
  91. package/dist/middleware/openapi.d.ts +64 -0
  92. package/dist/middleware/openapi.d.ts.map +1 -0
  93. package/dist/middleware/openapi.js +258 -0
  94. package/dist/middleware/openapi.js.map +1 -0
  95. package/dist/middleware/requestLogging.d.ts +22 -0
  96. package/dist/middleware/requestLogging.d.ts.map +1 -0
  97. package/dist/middleware/requestLogging.js +61 -0
  98. package/dist/middleware/requestLogging.js.map +1 -0
  99. package/dist/middleware/session.d.ts +84 -0
  100. package/dist/middleware/session.d.ts.map +1 -0
  101. package/dist/middleware/session.js +189 -0
  102. package/dist/middleware/session.js.map +1 -0
  103. package/dist/middleware/validation.d.ts +1337 -0
  104. package/dist/middleware/validation.d.ts.map +1 -0
  105. package/dist/middleware/validation.js +483 -0
  106. package/dist/middleware/validation.js.map +1 -0
  107. package/dist/services/aiService.d.ts +180 -0
  108. package/dist/services/aiService.d.ts.map +1 -0
  109. package/dist/services/aiService.js +547 -0
  110. package/dist/services/aiService.js.map +1 -0
  111. package/dist/services/conversationStorage.d.ts +38 -0
  112. package/dist/services/conversationStorage.d.ts.map +1 -0
  113. package/dist/services/conversationStorage.js +158 -0
  114. package/dist/services/conversationStorage.js.map +1 -0
  115. package/dist/services/crossPlatformBuffer.d.ts +84 -0
  116. package/dist/services/crossPlatformBuffer.d.ts.map +1 -0
  117. package/dist/services/crossPlatformBuffer.js +246 -0
  118. package/dist/services/crossPlatformBuffer.js.map +1 -0
  119. package/dist/services/index.d.ts +17 -0
  120. package/dist/services/index.d.ts.map +1 -0
  121. package/dist/services/index.js +18 -0
  122. package/dist/services/index.js.map +1 -0
  123. package/dist/services/networkService.d.ts +81 -0
  124. package/dist/services/networkService.d.ts.map +1 -0
  125. package/dist/services/networkService.js +268 -0
  126. package/dist/services/networkService.js.map +1 -0
  127. package/dist/services/queueService.d.ts +112 -0
  128. package/dist/services/queueService.d.ts.map +1 -0
  129. package/dist/services/queueService.js +338 -0
  130. package/dist/services/queueService.js.map +1 -0
  131. package/dist/services/settingsService.d.ts +135 -0
  132. package/dist/services/settingsService.d.ts.map +1 -0
  133. package/dist/services/settingsService.js +425 -0
  134. package/dist/services/settingsService.js.map +1 -0
  135. package/dist/services/systemMonitor.d.ts +208 -0
  136. package/dist/services/systemMonitor.d.ts.map +1 -0
  137. package/dist/services/systemMonitor.js +693 -0
  138. package/dist/services/systemMonitor.js.map +1 -0
  139. package/dist/services/updateService.d.ts +78 -0
  140. package/dist/services/updateService.d.ts.map +1 -0
  141. package/dist/services/updateService.js +252 -0
  142. package/dist/services/updateService.js.map +1 -0
  143. package/dist/services/websocketEvents.d.ts +372 -0
  144. package/dist/services/websocketEvents.d.ts.map +1 -0
  145. package/dist/services/websocketEvents.js +338 -0
  146. package/dist/services/websocketEvents.js.map +1 -0
  147. package/dist/services/websocketServer.d.ts +80 -0
  148. package/dist/services/websocketServer.d.ts.map +1 -0
  149. package/dist/services/websocketServer.js +299 -0
  150. package/dist/services/websocketServer.js.map +1 -0
  151. package/dist/settings/SettingsSchema.d.ts +151 -0
  152. package/dist/settings/SettingsSchema.d.ts.map +1 -0
  153. package/dist/settings/SettingsSchema.js +424 -0
  154. package/dist/settings/SettingsSchema.js.map +1 -0
  155. package/dist/testing/TestServer.d.ts +69 -0
  156. package/dist/testing/TestServer.d.ts.map +1 -0
  157. package/dist/testing/TestServer.js +250 -0
  158. package/dist/testing/TestServer.js.map +1 -0
  159. package/dist/types/index.d.ts +137 -0
  160. package/dist/types/index.d.ts.map +1 -0
  161. package/dist/types/index.js +5 -0
  162. package/dist/types/index.js.map +1 -0
  163. package/dist/utils/appPaths.d.ts +74 -0
  164. package/dist/utils/appPaths.d.ts.map +1 -0
  165. package/dist/utils/appPaths.js +162 -0
  166. package/dist/utils/appPaths.js.map +1 -0
  167. package/dist/utils/fs-utils.d.ts +50 -0
  168. package/dist/utils/fs-utils.d.ts.map +1 -0
  169. package/dist/utils/fs-utils.js +114 -0
  170. package/dist/utils/fs-utils.js.map +1 -0
  171. package/dist/utils/index.d.ts +12 -0
  172. package/dist/utils/index.d.ts.map +1 -0
  173. package/dist/utils/index.js +10 -0
  174. package/dist/utils/index.js.map +1 -0
  175. package/dist/utils/standardConfig.d.ts +61 -0
  176. package/dist/utils/standardConfig.d.ts.map +1 -0
  177. package/dist/utils/standardConfig.js +109 -0
  178. package/dist/utils/standardConfig.js.map +1 -0
  179. package/dist/utils/startupBanner.d.ts +34 -0
  180. package/dist/utils/startupBanner.d.ts.map +1 -0
  181. package/dist/utils/startupBanner.js +169 -0
  182. package/dist/utils/startupBanner.js.map +1 -0
  183. package/dist/utils/startupLogger.d.ts +45 -0
  184. package/dist/utils/startupLogger.d.ts.map +1 -0
  185. package/dist/utils/startupLogger.js +200 -0
  186. package/dist/utils/startupLogger.js.map +1 -0
  187. package/package.json +151 -0
  188. package/src/api/logsRouter.ts +600 -0
  189. package/src/cli/dev-server.ts +803 -0
  190. package/src/cli/index.ts +31 -0
  191. package/src/core/StandardServer.ts +587 -0
  192. package/src/core/apiResponse.ts +202 -0
  193. package/src/core/healthCheck.ts +565 -0
  194. package/src/core/index.ts +80 -0
  195. package/src/core/logger.ts +1092 -0
  196. package/src/core/portUtils.ts +319 -0
  197. package/src/core/storageService.ts +595 -0
  198. package/src/desktop/bundler.ts +271 -0
  199. package/src/desktop/index.ts +18 -0
  200. package/src/desktop/native-modules.ts +289 -0
  201. package/src/index.ts +142 -0
  202. package/src/logging/LogCategories.ts +302 -0
  203. package/src/middleware/aiErrorHandler.ts +278 -0
  204. package/src/middleware/auth.ts +329 -0
  205. package/src/middleware/cors.ts +187 -0
  206. package/src/middleware/errorHandler.ts +103 -0
  207. package/src/middleware/fileUpload.ts +252 -0
  208. package/src/middleware/health.ts +206 -0
  209. package/src/middleware/index.ts +71 -0
  210. package/src/middleware/openapi.ts +305 -0
  211. package/src/middleware/requestLogging.ts +92 -0
  212. package/src/middleware/session.ts +238 -0
  213. package/src/middleware/validation.ts +603 -0
  214. package/src/services/aiService.ts +789 -0
  215. package/src/services/conversationStorage.ts +232 -0
  216. package/src/services/crossPlatformBuffer.ts +341 -0
  217. package/src/services/index.ts +47 -0
  218. package/src/services/networkService.ts +351 -0
  219. package/src/services/queueService.ts +446 -0
  220. package/src/services/settingsService.ts +549 -0
  221. package/src/services/systemMonitor.ts +936 -0
  222. package/src/services/updateService.ts +334 -0
  223. package/src/services/websocketEvents.ts +409 -0
  224. package/src/services/websocketServer.ts +394 -0
  225. package/src/settings/SettingsSchema.ts +664 -0
  226. package/src/testing/TestServer.ts +312 -0
  227. package/src/types/index.ts +154 -0
  228. package/src/utils/appPaths.ts +196 -0
  229. package/src/utils/fs-utils.ts +130 -0
  230. package/src/utils/index.ts +15 -0
  231. package/src/utils/standardConfig.ts +178 -0
  232. package/src/utils/startupBanner.ts +287 -0
  233. package/src/utils/startupLogger.ts +268 -0
  234. package/ui/dist/index.d.mts +1221 -0
  235. package/ui/dist/index.d.ts +1221 -0
  236. package/ui/dist/index.js +73 -0
  237. package/ui/dist/index.js.map +1 -0
  238. package/ui/dist/index.mjs +73 -0
  239. package/ui/dist/index.mjs.map +1 -0
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Conversation Storage Service
3
+ * Provides persistent storage for AI conversations using lowdb
4
+ */
5
+
6
+ import { Low } from "lowdb";
7
+ import { JSONFile } from "lowdb/node";
8
+ import path from "path";
9
+ import { ensureDir } from "fs-extra";
10
+ import { createLogger } from "../core/index.js";
11
+ let logger: any; // Will be initialized when needed
12
+
13
+ function ensureLogger() {
14
+ if (!logger) {
15
+ logger = createLogger("ConversationStorage");
16
+ }
17
+ return logger;
18
+ }
19
+
20
+ interface Message {
21
+ role: "user" | "assistant" | "system";
22
+ content: string;
23
+ timestamp?: string;
24
+ }
25
+
26
+ interface Conversation {
27
+ id: string;
28
+ title?: string;
29
+ messages: Message[];
30
+ metadata?: Record<string, any>;
31
+ createdAt: string;
32
+ updatedAt: string;
33
+ }
34
+
35
+ interface ConversationsDB {
36
+ conversations: Record<string, Conversation>;
37
+ }
38
+
39
+ const defaultData: ConversationsDB = {
40
+ conversations: {},
41
+ };
42
+
43
+ class ConversationStorage {
44
+ private db: Low<ConversationsDB> | null = null;
45
+ private initialized: boolean = false;
46
+
47
+ async initialize(): Promise<void> {
48
+ if (this.initialized) return;
49
+
50
+ try {
51
+ // Ensure data directory exists
52
+ const dataDir = path.join(process.cwd(), "data");
53
+ await ensureDir(dataDir);
54
+
55
+ // Initialize lowdb with JSON file adapter
56
+ const dbPath = path.join(dataDir, "conversations.json");
57
+ const adapter = new JSONFile<ConversationsDB>(dbPath);
58
+ this.db = new Low<ConversationsDB>(adapter, defaultData);
59
+
60
+ // Read data from file
61
+ await this.db.read();
62
+
63
+ // Initialize with default data if file doesn't exist
64
+ if (!this.db.data) {
65
+ this.db.data = defaultData;
66
+ await this.db.write();
67
+ }
68
+
69
+ // Ensure conversations object exists
70
+ if (!this.db.data.conversations) {
71
+ this.db.data.conversations = {};
72
+ await this.db.write();
73
+ }
74
+
75
+ this.initialized = true;
76
+ ensureLogger().info("Conversation storage initialized");
77
+ } catch (_error) {
78
+ ensureLogger().error(
79
+ "Failed to initialize conversation storage:",
80
+ _error,
81
+ );
82
+ throw _error;
83
+ }
84
+ }
85
+
86
+ async getConversation(conversationId: string): Promise<Conversation | null> {
87
+ await this.initialize();
88
+ return this.db!.data!.conversations[conversationId] || null;
89
+ }
90
+
91
+ async saveConversation(
92
+ conversationId: string,
93
+ conversation: Partial<Conversation>,
94
+ ): Promise<Conversation> {
95
+ await this.initialize();
96
+
97
+ const now = new Date().toISOString();
98
+ const existing = this.db!.data!.conversations[conversationId];
99
+ const fullConversation: Conversation = {
100
+ ...existing,
101
+ ...conversation,
102
+ id: conversationId,
103
+ messages: conversation.messages ?? existing?.messages ?? [],
104
+ createdAt: existing?.createdAt ?? conversation.createdAt ?? now,
105
+ updatedAt: now,
106
+ };
107
+
108
+ this.db!.data!.conversations[conversationId] = fullConversation;
109
+ await this.db!.write();
110
+
111
+ ensureLogger().debug(`Saved conversation: ${conversationId}`);
112
+ return fullConversation;
113
+ }
114
+
115
+ async deleteConversation(conversationId: string): Promise<boolean> {
116
+ await this.initialize();
117
+
118
+ if (this.db!.data!.conversations[conversationId]) {
119
+ delete this.db!.data!.conversations[conversationId];
120
+ await this.db!.write();
121
+ ensureLogger().debug(`Deleted conversation: ${conversationId}`);
122
+ return true;
123
+ }
124
+
125
+ return false;
126
+ }
127
+
128
+ async getAllConversations(): Promise<Conversation[]> {
129
+ await this.initialize();
130
+ return Object.values(this.db!.data!.conversations);
131
+ }
132
+
133
+ async getRecentConversations(limit: number = 10): Promise<Conversation[]> {
134
+ await this.initialize();
135
+ const conversations = Object.values(this.db!.data!.conversations);
136
+
137
+ return conversations
138
+ .sort(
139
+ (a, b) =>
140
+ new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),
141
+ )
142
+ .slice(0, limit);
143
+ }
144
+
145
+ async addMessage(
146
+ conversationId: string,
147
+ message: Message,
148
+ ): Promise<Conversation> {
149
+ await this.initialize();
150
+
151
+ let conversation = this.db!.data!.conversations[conversationId];
152
+
153
+ if (!conversation) {
154
+ conversation = {
155
+ id: conversationId,
156
+ messages: [],
157
+ createdAt: new Date().toISOString(),
158
+ updatedAt: new Date().toISOString(),
159
+ };
160
+ }
161
+
162
+ message.timestamp = message.timestamp || new Date().toISOString();
163
+ conversation.messages.push(message);
164
+ conversation.updatedAt = new Date().toISOString();
165
+
166
+ this.db!.data!.conversations[conversationId] = conversation;
167
+ await this.db!.write();
168
+
169
+ return conversation;
170
+ }
171
+
172
+ async clearAllConversations(): Promise<void> {
173
+ await this.initialize();
174
+ this.db!.data!.conversations = {};
175
+ await this.db!.write();
176
+ ensureLogger().info("Cleared all conversations");
177
+ }
178
+
179
+ async exportConversations(): Promise<ConversationsDB> {
180
+ await this.initialize();
181
+ return { ...this.db!.data! };
182
+ }
183
+
184
+ async importConversations(data: ConversationsDB): Promise<void> {
185
+ await this.initialize();
186
+ this.db!.data = data;
187
+ await this.db!.write();
188
+ ensureLogger().info("Imported conversations");
189
+ }
190
+
191
+ async getConversationStats(): Promise<Record<string, any>> {
192
+ await this.initialize();
193
+ const conversations = Object.values(this.db!.data!.conversations);
194
+
195
+ return {
196
+ total: conversations.length,
197
+ totalMessages: conversations.reduce(
198
+ (sum, c) => sum + c.messages.length,
199
+ 0,
200
+ ),
201
+ averageLength:
202
+ conversations.length > 0
203
+ ? conversations.reduce((sum, c) => sum + c.messages.length, 0) /
204
+ conversations.length
205
+ : 0,
206
+ oldestConversation:
207
+ conversations.length > 0
208
+ ? conversations.reduce((oldest, c) =>
209
+ new Date(c.createdAt) < new Date(oldest.createdAt) ? c : oldest,
210
+ ).createdAt
211
+ : null,
212
+ newestConversation:
213
+ conversations.length > 0
214
+ ? conversations.reduce((newest, c) =>
215
+ new Date(c.createdAt) > new Date(newest.createdAt) ? c : newest,
216
+ ).createdAt
217
+ : null,
218
+ };
219
+ }
220
+ }
221
+
222
+ // Singleton instance
223
+ let conversationStorage: ConversationStorage | null = null;
224
+
225
+ export function getConversationStorage(): ConversationStorage {
226
+ if (!conversationStorage) {
227
+ conversationStorage = new ConversationStorage();
228
+ }
229
+ return conversationStorage;
230
+ }
231
+
232
+ export default ConversationStorage;
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Cross-Platform Buffer Handling Module
3
+ *
4
+ * Ensures consistent data representation across ARM and x86 architectures
5
+ * by using explicit buffer operations that are not affected by processor endianness.
6
+ */
7
+
8
+ export type Endianness = "LE" | "BE";
9
+ export type DataType =
10
+ | "uint16"
11
+ | "int16"
12
+ | "uint32"
13
+ | "int32"
14
+ | "float32"
15
+ | "float64"
16
+ | "bool";
17
+
18
+ export interface BufferOptions {
19
+ endian?: Endianness;
20
+ wordSwap?: boolean;
21
+ byteSwap?: boolean;
22
+ }
23
+
24
+ export class CrossPlatformBuffer {
25
+ private systemEndianness: Endianness;
26
+
27
+ constructor() {
28
+ // Detect system endianness for debugging/logging purposes
29
+ this.systemEndianness = this.detectSystemEndianness();
30
+ }
31
+
32
+ /**
33
+ * Detect system endianness (for logging/debugging only)
34
+ */
35
+ private detectSystemEndianness(): Endianness {
36
+ const arrayBuffer = new ArrayBuffer(2);
37
+ const uint8Array = new Uint8Array(arrayBuffer);
38
+ const uint16Array = new Uint16Array(arrayBuffer);
39
+
40
+ uint16Array[0] = 0x1234;
41
+
42
+ if (uint8Array[0] === 0x12) {
43
+ return "BE"; // Big Endian
44
+ } else {
45
+ return "LE"; // Little Endian
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Get system endianness
51
+ */
52
+ getSystemEndianness(): Endianness {
53
+ return this.systemEndianness;
54
+ }
55
+
56
+ /**
57
+ * Convert float32 to two 16-bit registers with explicit endianness control
58
+ */
59
+ float32ToRegisters(
60
+ value: number,
61
+ endian: Endianness = "LE",
62
+ wordSwap: boolean = false,
63
+ byteSwap: boolean = false,
64
+ ): [number, number] {
65
+ // Create a buffer to hold the float32
66
+ const buffer = new ArrayBuffer(4);
67
+ const float32View = new Float32Array(buffer);
68
+ const dataView = new DataView(buffer);
69
+
70
+ // Write the float32 value
71
+ float32View[0] = value;
72
+
73
+ // Read as two 16-bit values with specified endianness
74
+ let reg1: number, reg2: number;
75
+
76
+ if (endian === "BE") {
77
+ // Big Endian: most significant word first
78
+ reg1 = dataView.getUint16(0, false); // Big endian read
79
+ reg2 = dataView.getUint16(2, false);
80
+ } else {
81
+ // Little Endian: least significant word first
82
+ reg1 = dataView.getUint16(0, true); // Little endian read
83
+ reg2 = dataView.getUint16(2, true);
84
+ }
85
+
86
+ // Apply word swap if needed
87
+ if (wordSwap) {
88
+ [reg1, reg2] = [reg2, reg1];
89
+ }
90
+
91
+ // Apply byte swap within each word if needed
92
+ if (byteSwap) {
93
+ reg1 = ((reg1 & 0xff) << 8) | ((reg1 >> 8) & 0xff);
94
+ reg2 = ((reg2 & 0xff) << 8) | ((reg2 >> 8) & 0xff);
95
+ }
96
+
97
+ return [reg1, reg2];
98
+ }
99
+
100
+ /**
101
+ * Convert two 16-bit registers to float32 with explicit endianness control
102
+ */
103
+ registersToFloat32(
104
+ reg1: number,
105
+ reg2: number,
106
+ endian: Endianness = "LE",
107
+ wordSwap: boolean = false,
108
+ byteSwap: boolean = false,
109
+ ): number {
110
+ // Apply byte swap within each word if needed
111
+ if (byteSwap) {
112
+ reg1 = ((reg1 & 0xff) << 8) | ((reg1 >> 8) & 0xff);
113
+ reg2 = ((reg2 & 0xff) << 8) | ((reg2 >> 8) & 0xff);
114
+ }
115
+
116
+ // Apply word swap if needed
117
+ if (wordSwap) {
118
+ [reg1, reg2] = [reg2, reg1];
119
+ }
120
+
121
+ // Create a buffer and write the registers
122
+ const buffer = new ArrayBuffer(4);
123
+ const dataView = new DataView(buffer);
124
+
125
+ if (endian === "BE") {
126
+ // Big Endian: write as big endian
127
+ dataView.setUint16(0, reg1, false);
128
+ dataView.setUint16(2, reg2, false);
129
+ } else {
130
+ // Little Endian: write as little endian
131
+ dataView.setUint16(0, reg1, true);
132
+ dataView.setUint16(2, reg2, true);
133
+ }
134
+
135
+ // Read as float32
136
+ const float32View = new Float32Array(buffer);
137
+ return float32View[0];
138
+ }
139
+
140
+ /**
141
+ * Convert int32 to two 16-bit registers
142
+ */
143
+ int32ToRegisters(
144
+ value: number,
145
+ endian: Endianness = "LE",
146
+ wordSwap: boolean = false,
147
+ ): [number, number] {
148
+ const buffer = new ArrayBuffer(4);
149
+ const dataView = new DataView(buffer);
150
+
151
+ // Write the int32 value
152
+ dataView.setInt32(0, value, endian === "LE");
153
+
154
+ // Read as two 16-bit values
155
+ let reg1 = dataView.getUint16(0, endian === "LE");
156
+ let reg2 = dataView.getUint16(2, endian === "LE");
157
+
158
+ if (wordSwap) {
159
+ [reg1, reg2] = [reg2, reg1];
160
+ }
161
+
162
+ return [reg1, reg2];
163
+ }
164
+
165
+ /**
166
+ * Convert two 16-bit registers to int32
167
+ */
168
+ registersToInt32(
169
+ reg1: number,
170
+ reg2: number,
171
+ endian: Endianness = "LE",
172
+ wordSwap: boolean = false,
173
+ ): number {
174
+ if (wordSwap) {
175
+ [reg1, reg2] = [reg2, reg1];
176
+ }
177
+
178
+ const buffer = new ArrayBuffer(4);
179
+ const dataView = new DataView(buffer);
180
+
181
+ dataView.setUint16(0, reg1, endian === "LE");
182
+ dataView.setUint16(2, reg2, endian === "LE");
183
+
184
+ return dataView.getInt32(0, endian === "LE");
185
+ }
186
+
187
+ /**
188
+ * Convert uint32 to two 16-bit registers
189
+ */
190
+ uint32ToRegisters(
191
+ value: number,
192
+ endian: Endianness = "LE",
193
+ wordSwap: boolean = false,
194
+ ): [number, number] {
195
+ const buffer = new ArrayBuffer(4);
196
+ const dataView = new DataView(buffer);
197
+
198
+ // Write the uint32 value
199
+ dataView.setUint32(0, value, endian === "LE");
200
+
201
+ // Read as two 16-bit values
202
+ let reg1 = dataView.getUint16(0, endian === "LE");
203
+ let reg2 = dataView.getUint16(2, endian === "LE");
204
+
205
+ if (wordSwap) {
206
+ [reg1, reg2] = [reg2, reg1];
207
+ }
208
+
209
+ return [reg1, reg2];
210
+ }
211
+
212
+ /**
213
+ * Convert two 16-bit registers to uint32
214
+ */
215
+ registersToUint32(
216
+ reg1: number,
217
+ reg2: number,
218
+ endian: Endianness = "LE",
219
+ wordSwap: boolean = false,
220
+ ): number {
221
+ if (wordSwap) {
222
+ [reg1, reg2] = [reg2, reg1];
223
+ }
224
+
225
+ const buffer = new ArrayBuffer(4);
226
+ const dataView = new DataView(buffer);
227
+
228
+ dataView.setUint16(0, reg1, endian === "LE");
229
+ dataView.setUint16(2, reg2, endian === "LE");
230
+
231
+ return dataView.getUint32(0, endian === "LE");
232
+ }
233
+
234
+ /**
235
+ * Convert boolean to register value
236
+ */
237
+ boolToRegister(value: boolean): number {
238
+ return value ? 1 : 0;
239
+ }
240
+
241
+ /**
242
+ * Convert register value to boolean
243
+ */
244
+ registerToBool(value: number): boolean {
245
+ return value !== 0;
246
+ }
247
+
248
+ /**
249
+ * Convert int16 to register with proper sign extension
250
+ */
251
+ int16ToRegister(value: number): number {
252
+ // Ensure value is within int16 range
253
+ value = Math.max(-32768, Math.min(32767, value));
254
+
255
+ // Convert to unsigned representation
256
+ if (value < 0) {
257
+ return 0x10000 + value; // Two's complement
258
+ }
259
+ return value;
260
+ }
261
+
262
+ /**
263
+ * Convert register to int16 with proper sign handling
264
+ */
265
+ registerToInt16(value: number): number {
266
+ // Check if the sign bit is set
267
+ if (value & 0x8000) {
268
+ // Negative number in two's complement
269
+ return value - 0x10000;
270
+ }
271
+ return value;
272
+ }
273
+
274
+ /**
275
+ * Convert string to register array
276
+ */
277
+ stringToRegisters(str: string, maxLength: number = 32): number[] {
278
+ const registers: number[] = [];
279
+ const buffer = Buffer.from(str, "utf8");
280
+
281
+ // Pad with zeros to ensure even number of bytes
282
+ const paddedLength = Math.min(maxLength, Math.ceil(buffer.length / 2) * 2);
283
+
284
+ for (let i = 0; i < paddedLength; i += 2) {
285
+ const byte1 = buffer[i] || 0;
286
+ const byte2 = buffer[i + 1] || 0;
287
+ registers.push((byte1 << 8) | byte2);
288
+ }
289
+
290
+ return registers;
291
+ }
292
+
293
+ /**
294
+ * Convert register array to string
295
+ */
296
+ registersToString(registers: number[]): string {
297
+ const bytes: number[] = [];
298
+
299
+ for (const reg of registers) {
300
+ bytes.push((reg >> 8) & 0xff); // High byte
301
+ bytes.push(reg & 0xff); // Low byte
302
+ }
303
+
304
+ // Remove trailing zeros
305
+ while (bytes.length > 0 && bytes[bytes.length - 1] === 0) {
306
+ bytes.pop();
307
+ }
308
+
309
+ return Buffer.from(bytes).toString("utf8");
310
+ }
311
+
312
+ /**
313
+ * Validate register value is within 16-bit range
314
+ */
315
+ validateRegisterValue(value: number): boolean {
316
+ return Number.isInteger(value) && value >= 0 && value <= 0xffff;
317
+ }
318
+
319
+ /**
320
+ * Create a buffer configuration for consistent handling
321
+ */
322
+ createBufferConfig(options: BufferOptions = {}): Required<BufferOptions> {
323
+ return {
324
+ endian: options.endian || "LE",
325
+ wordSwap: options.wordSwap || false,
326
+ byteSwap: options.byteSwap || false,
327
+ };
328
+ }
329
+ }
330
+
331
+ // Singleton instance
332
+ let crossPlatformBuffer: CrossPlatformBuffer | null = null;
333
+
334
+ export function getCrossPlatformBuffer(): CrossPlatformBuffer {
335
+ if (!crossPlatformBuffer) {
336
+ crossPlatformBuffer = new CrossPlatformBuffer();
337
+ }
338
+ return crossPlatformBuffer;
339
+ }
340
+
341
+ export default CrossPlatformBuffer;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Services Module Exports
3
+ */
4
+
5
+ // Configuration management - use SettingsService
6
+
7
+ // Other services
8
+ export { getConversationStorage } from "./conversationStorage.js";
9
+ export { CrossPlatformBuffer } from "./crossPlatformBuffer.js";
10
+ export { getNetworkService } from "./networkService.js";
11
+ export { getUpdateService } from "./updateService.js";
12
+ export {
13
+ createWebSocketServer,
14
+ getWebSocketServer,
15
+ } from "./websocketServer.js";
16
+ export {
17
+ SettingsService,
18
+ CommonSettingsCategories,
19
+ } from "./settingsService.js";
20
+ export type {
21
+ SettingsCategory,
22
+ SettingsField,
23
+ SettingsOptions,
24
+ } from "./settingsService.js";
25
+
26
+ // WebSocket events
27
+ export {
28
+ WebSocketEventManager,
29
+ TypedEventEmitter,
30
+ EventTypes,
31
+ EventPatterns,
32
+ } from "./websocketEvents.js";
33
+ export type { EventPayload, EventResponse } from "./websocketEvents.js";
34
+
35
+ // AI Service
36
+ export { aiService, AIService } from "./aiService.js";
37
+ export type {
38
+ AIConfig,
39
+ AIMessage,
40
+ AIResponse,
41
+ AIAnalysisOptions,
42
+ AIProvider,
43
+ } from "./aiService.js";
44
+
45
+ // Queue Service
46
+ export { default as QueueService } from "./queueService.js";
47
+ export type { QueueJob, QueueConfig, JobHandler } from "./queueService.js";