@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.3

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 (120) hide show
  1. package/README.md +44 -54
  2. package/bin/cli.js +1 -115
  3. package/bin/loxia-terminal-v2.js +3 -0
  4. package/bin/loxia-terminal.js +3 -0
  5. package/bin/start-with-terminal.js +3 -0
  6. package/package.json +14 -15
  7. package/scripts/install-scanners.js +1 -235
  8. package/src/analyzers/CSSAnalyzer.js +1 -297
  9. package/src/analyzers/ConfigValidator.js +1 -690
  10. package/src/analyzers/ESLintAnalyzer.js +1 -320
  11. package/src/analyzers/JavaScriptAnalyzer.js +1 -261
  12. package/src/analyzers/PrettierFormatter.js +1 -247
  13. package/src/analyzers/PythonAnalyzer.js +1 -266
  14. package/src/analyzers/SecurityAnalyzer.js +1 -729
  15. package/src/analyzers/TypeScriptAnalyzer.js +1 -247
  16. package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
  17. package/src/analyzers/codeCloneDetector/detector.js +1 -203
  18. package/src/analyzers/codeCloneDetector/index.js +1 -160
  19. package/src/analyzers/codeCloneDetector/parser.js +1 -199
  20. package/src/analyzers/codeCloneDetector/reporter.js +1 -148
  21. package/src/analyzers/codeCloneDetector/scanner.js +1 -59
  22. package/src/core/agentPool.js +1 -1474
  23. package/src/core/agentScheduler.js +1 -2147
  24. package/src/core/contextManager.js +1 -709
  25. package/src/core/messageProcessor.js +1 -732
  26. package/src/core/orchestrator.js +1 -548
  27. package/src/core/stateManager.js +1 -877
  28. package/src/index.js +1 -631
  29. package/src/interfaces/cli.js +1 -549
  30. package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
  31. package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
  32. package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
  33. package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
  34. package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
  35. package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
  36. package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
  37. package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
  38. package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
  39. package/src/interfaces/terminal/api/apiClient.js +1 -0
  40. package/src/interfaces/terminal/api/messageRouter.js +1 -0
  41. package/src/interfaces/terminal/api/session.js +1 -0
  42. package/src/interfaces/terminal/api/websocket.js +1 -0
  43. package/src/interfaces/terminal/components/AgentCreator.js +1 -0
  44. package/src/interfaces/terminal/components/AgentEditor.js +1 -0
  45. package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
  46. package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
  47. package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
  48. package/src/interfaces/terminal/components/Header.js +1 -0
  49. package/src/interfaces/terminal/components/HelpPanel.js +1 -0
  50. package/src/interfaces/terminal/components/InputBox.js +1 -0
  51. package/src/interfaces/terminal/components/Layout.js +1 -0
  52. package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
  53. package/src/interfaces/terminal/components/MessageList.js +1 -0
  54. package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
  55. package/src/interfaces/terminal/components/SearchPanel.js +1 -0
  56. package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
  57. package/src/interfaces/terminal/components/StatusBar.js +1 -0
  58. package/src/interfaces/terminal/components/TextInput.js +1 -0
  59. package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
  60. package/src/interfaces/terminal/config/constants.js +1 -0
  61. package/src/interfaces/terminal/index.js +1 -0
  62. package/src/interfaces/terminal/state/useAgentControl.js +1 -0
  63. package/src/interfaces/terminal/state/useAgents.js +1 -0
  64. package/src/interfaces/terminal/state/useConnection.js +1 -0
  65. package/src/interfaces/terminal/state/useMessages.js +1 -0
  66. package/src/interfaces/terminal/state/useTools.js +1 -0
  67. package/src/interfaces/terminal/utils/debugLogger.js +1 -0
  68. package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
  69. package/src/interfaces/terminal/utils/theme.js +1 -0
  70. package/src/interfaces/webServer.js +1 -2162
  71. package/src/modules/fileExplorer/controller.js +1 -280
  72. package/src/modules/fileExplorer/index.js +1 -37
  73. package/src/modules/fileExplorer/middleware.js +1 -92
  74. package/src/modules/fileExplorer/routes.js +1 -125
  75. package/src/modules/fileExplorer/types.js +1 -44
  76. package/src/services/aiService.js +1 -1232
  77. package/src/services/apiKeyManager.js +1 -164
  78. package/src/services/benchmarkService.js +1 -366
  79. package/src/services/budgetService.js +1 -539
  80. package/src/services/contextInjectionService.js +1 -247
  81. package/src/services/conversationCompactionService.js +1 -637
  82. package/src/services/errorHandler.js +1 -810
  83. package/src/services/fileAttachmentService.js +1 -544
  84. package/src/services/modelRouterService.js +1 -366
  85. package/src/services/modelsService.js +1 -322
  86. package/src/services/qualityInspector.js +1 -796
  87. package/src/services/tokenCountingService.js +1 -536
  88. package/src/tools/agentCommunicationTool.js +1 -1344
  89. package/src/tools/agentDelayTool.js +1 -485
  90. package/src/tools/asyncToolManager.js +1 -604
  91. package/src/tools/baseTool.js +1 -800
  92. package/src/tools/browserTool.js +1 -920
  93. package/src/tools/cloneDetectionTool.js +1 -621
  94. package/src/tools/dependencyResolverTool.js +1 -1215
  95. package/src/tools/fileContentReplaceTool.js +1 -875
  96. package/src/tools/fileSystemTool.js +1 -1107
  97. package/src/tools/fileTreeTool.js +1 -853
  98. package/src/tools/imageTool.js +1 -901
  99. package/src/tools/importAnalyzerTool.js +1 -1060
  100. package/src/tools/jobDoneTool.js +1 -248
  101. package/src/tools/seekTool.js +1 -956
  102. package/src/tools/staticAnalysisTool.js +1 -1778
  103. package/src/tools/taskManagerTool.js +1 -2873
  104. package/src/tools/terminalTool.js +1 -2304
  105. package/src/tools/webTool.js +1 -1430
  106. package/src/types/agent.js +1 -519
  107. package/src/types/contextReference.js +1 -972
  108. package/src/types/conversation.js +1 -730
  109. package/src/types/toolCommand.js +1 -747
  110. package/src/utilities/attachmentValidator.js +1 -292
  111. package/src/utilities/configManager.js +1 -582
  112. package/src/utilities/constants.js +1 -722
  113. package/src/utilities/directoryAccessManager.js +1 -535
  114. package/src/utilities/fileProcessor.js +1 -307
  115. package/src/utilities/logger.js +1 -436
  116. package/src/utilities/tagParser.js +1 -1246
  117. package/src/utilities/toolConstants.js +1 -317
  118. package/web-ui/build/index.html +2 -2
  119. package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
  120. package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
@@ -1,544 +1 @@
1
- /**
2
- * File Attachment Service
3
- * Manages file attachments for agents with CRUD operations and reference counting
4
- */
5
-
6
- import path from 'path';
7
- import { fileURLToPath } from 'url';
8
- import { randomUUID } from 'crypto';
9
- import FileProcessor from '../utilities/fileProcessor.js';
10
- import AttachmentValidator from '../utilities/attachmentValidator.js';
11
-
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = path.dirname(__filename);
14
-
15
- const ATTACHMENTS_DIR = path.join(process.cwd(), 'loxia-state', 'attachments');
16
- const INDEX_FILE = path.join(ATTACHMENTS_DIR, 'attachments-index.json');
17
-
18
- class FileAttachmentService {
19
- constructor(config = {}, logger = null) {
20
- this.config = config;
21
- this.logger = logger;
22
- this.fileProcessor = new FileProcessor(config, logger);
23
- this.validator = new AttachmentValidator(config, logger);
24
- this.index = null; // Lazy loaded
25
- }
26
-
27
- /**
28
- * Initialize service (create directories, load index)
29
- * @returns {Promise<void>}
30
- */
31
- async initialize() {
32
- try {
33
- await this.fileProcessor.createDirectory(ATTACHMENTS_DIR);
34
- await this.loadIndex();
35
- this.logger?.info('FileAttachmentService initialized', { attachmentsDir: ATTACHMENTS_DIR });
36
- } catch (error) {
37
- this.logger?.error('Error initializing FileAttachmentService', { error: error.message });
38
- throw error;
39
- }
40
- }
41
-
42
- /**
43
- * Load index file
44
- * @returns {Promise<Object>}
45
- */
46
- async loadIndex() {
47
- try {
48
- const exists = await this.fileProcessor.fileExists(INDEX_FILE);
49
- if (!exists) {
50
- this.index = { attachments: {}, agentRefs: {} };
51
- await this.saveIndex();
52
- } else {
53
- const content = await this.fileProcessor.readFile(INDEX_FILE, 'utf8');
54
- this.index = JSON.parse(content);
55
- }
56
- return this.index;
57
- } catch (error) {
58
- this.logger?.error('Error loading index', { error: error.message });
59
- this.index = { attachments: {}, agentRefs: {} };
60
- return this.index;
61
- }
62
- }
63
-
64
- /**
65
- * Save index file
66
- * @returns {Promise<void>}
67
- */
68
- async saveIndex() {
69
- try {
70
- await this.fileProcessor.writeFile(INDEX_FILE, JSON.stringify(this.index, null, 2), 'utf8');
71
- } catch (error) {
72
- this.logger?.error('Error saving index', { error: error.message });
73
- throw error;
74
- }
75
- }
76
-
77
- /**
78
- * Upload file attachment
79
- * @param {Object} options
80
- * @param {string} options.agentId - Agent ID
81
- * @param {string} options.filePath - Source file path
82
- * @param {string} options.mode - 'content' or 'reference'
83
- * @param {string} options.fileName - Optional custom file name
84
- * @returns {Promise<Object>} Attachment metadata
85
- */
86
- async uploadFile({ agentId, filePath, mode = 'content', fileName = null }) {
87
- if (!this.index) {
88
- await this.loadIndex();
89
- }
90
-
91
- try {
92
- // Validate file exists
93
- const exists = await this.fileProcessor.fileExists(filePath);
94
- if (!exists) {
95
- throw new Error(`File not found: ${filePath}`);
96
- }
97
-
98
- // Get file stats
99
- const stats = await this.fileProcessor.getFileStats(filePath);
100
- const actualFileName = fileName || path.basename(filePath);
101
- const fileExtension = path.extname(actualFileName);
102
-
103
- // Validate
104
- const validation = this.validator.validate({
105
- fileName: actualFileName,
106
- size: stats.size,
107
- mode,
108
- path: mode === 'reference' ? filePath : null
109
- });
110
-
111
- if (!validation.valid) {
112
- throw new Error(`Validation failed: ${validation.errors.join(', ')}`);
113
- }
114
-
115
- // Generate file ID
116
- const fileId = randomUUID();
117
-
118
- // Calculate hash
119
- const hash = await this.fileProcessor.calculateHash(filePath);
120
-
121
- // Determine content type
122
- const contentType = this.validator.getContentType(actualFileName);
123
-
124
- // Create attachment directory
125
- const attachmentDir = path.join(ATTACHMENTS_DIR, agentId, fileId);
126
- await this.fileProcessor.createDirectory(attachmentDir);
127
-
128
- // Process and save content (for content mode)
129
- let tokenEstimate = 0;
130
- let contentFileName = null;
131
-
132
- if (mode === 'content') {
133
- const processResult = await this.fileProcessor.processFile(filePath, contentType);
134
- const content = processResult.content;
135
-
136
- // Determine content file name based on type
137
- if (contentType === 'text') {
138
- contentFileName = 'content.txt';
139
- } else if (contentType === 'image') {
140
- contentFileName = 'content.base64';
141
- } else if (contentType === 'pdf') {
142
- contentFileName = 'content.txt';
143
- }
144
-
145
- // Save content
146
- const contentFilePath = path.join(attachmentDir, contentFileName);
147
- await this.fileProcessor.writeFile(contentFilePath, content, 'utf8');
148
-
149
- // Estimate tokens
150
- tokenEstimate = this.fileProcessor.estimateTokens(content);
151
- }
152
-
153
- // Create metadata
154
- const metadata = {
155
- fileId,
156
- agentId,
157
- fileName: actualFileName,
158
- originalPath: filePath,
159
- fileType: this.validator.getMimeType(actualFileName),
160
- fileExtension,
161
- size: stats.size,
162
- mode,
163
- active: true,
164
- uploadedAt: new Date().toISOString(),
165
- lastModified: stats.modified.toISOString(),
166
- hash,
167
- tokenEstimate,
168
- contentType,
169
- contentFileName,
170
- warnings: validation.warnings,
171
- sizeLevel: validation.sizeLevel,
172
- importedFrom: null,
173
- referencedBy: [agentId] // Reference counting
174
- };
175
-
176
- // Save metadata
177
- const metadataPath = path.join(attachmentDir, 'metadata.json');
178
- await this.fileProcessor.writeFile(metadataPath, JSON.stringify(metadata, null, 2), 'utf8');
179
-
180
- // Update index
181
- this.index.attachments[fileId] = {
182
- fileId,
183
- agentId,
184
- fileName: actualFileName,
185
- mode,
186
- active: metadata.active,
187
- referencedBy: metadata.referencedBy
188
- };
189
-
190
- if (!this.index.agentRefs[agentId]) {
191
- this.index.agentRefs[agentId] = [];
192
- }
193
- this.index.agentRefs[agentId].push(fileId);
194
-
195
- await this.saveIndex();
196
-
197
- this.logger?.info('File uploaded', { fileId, agentId, fileName: actualFileName, mode });
198
-
199
- return metadata;
200
- } catch (error) {
201
- this.logger?.error('Error uploading file', { agentId, filePath, error: error.message });
202
- throw error;
203
- }
204
- }
205
-
206
- /**
207
- * Get attachments for an agent
208
- * @param {string} agentId - Agent ID
209
- * @param {Object} filters - Optional filters { active, mode }
210
- * @returns {Promise<Array>} Array of attachment metadata
211
- */
212
- async getAttachments(agentId, filters = {}) {
213
- if (!this.index) {
214
- await this.loadIndex();
215
- }
216
-
217
- try {
218
- const fileIds = this.index.agentRefs[agentId] || [];
219
- const attachments = [];
220
-
221
- for (const fileId of fileIds) {
222
- const metadata = await this.getAttachment(fileId);
223
- if (metadata) {
224
- // Apply filters
225
- if (filters.active !== undefined && metadata.active !== filters.active) {
226
- continue;
227
- }
228
- if (filters.mode && metadata.mode !== filters.mode) {
229
- continue;
230
- }
231
- attachments.push(metadata);
232
- }
233
- }
234
-
235
- return attachments;
236
- } catch (error) {
237
- this.logger?.error('Error getting attachments', { agentId, error: error.message });
238
- throw error;
239
- }
240
- }
241
-
242
- /**
243
- * Get single attachment
244
- * @param {string} fileId - File ID
245
- * @returns {Promise<Object|null>} Attachment metadata or null
246
- */
247
- async getAttachment(fileId) {
248
- if (!this.index) {
249
- await this.loadIndex();
250
- }
251
-
252
- try {
253
- const indexEntry = this.index.attachments[fileId];
254
- if (!indexEntry) {
255
- return null;
256
- }
257
-
258
- const metadataPath = path.join(ATTACHMENTS_DIR, indexEntry.agentId, fileId, 'metadata.json');
259
- const exists = await this.fileProcessor.fileExists(metadataPath);
260
-
261
- if (!exists) {
262
- this.logger?.warn('Metadata file not found', { fileId });
263
- return null;
264
- }
265
-
266
- const content = await this.fileProcessor.readFile(metadataPath, 'utf8');
267
- return JSON.parse(content);
268
- } catch (error) {
269
- this.logger?.error('Error getting attachment', { fileId, error: error.message });
270
- return null;
271
- }
272
- }
273
-
274
- /**
275
- * Get attachment content
276
- * @param {string} fileId - File ID
277
- * @returns {Promise<string|null>} File content or null
278
- */
279
- async getAttachmentContent(fileId) {
280
- try {
281
- const metadata = await this.getAttachment(fileId);
282
- if (!metadata || metadata.mode !== 'content') {
283
- return null;
284
- }
285
-
286
- const contentPath = path.join(ATTACHMENTS_DIR, metadata.agentId, fileId, metadata.contentFileName);
287
- const exists = await this.fileProcessor.fileExists(contentPath);
288
-
289
- if (!exists) {
290
- return null;
291
- }
292
-
293
- return await this.fileProcessor.readFile(contentPath, 'utf8');
294
- } catch (error) {
295
- this.logger?.error('Error getting attachment content', { fileId, error: error.message });
296
- return null;
297
- }
298
- }
299
-
300
- /**
301
- * Toggle attachment active state
302
- * @param {string} fileId - File ID
303
- * @returns {Promise<Object>} Updated metadata
304
- */
305
- async toggleActive(fileId) {
306
- try {
307
- const metadata = await this.getAttachment(fileId);
308
- if (!metadata) {
309
- throw new Error(`Attachment not found: ${fileId}`);
310
- }
311
-
312
- metadata.active = !metadata.active;
313
- metadata.lastModified = new Date().toISOString();
314
-
315
- // Save updated metadata
316
- const metadataPath = path.join(ATTACHMENTS_DIR, metadata.agentId, fileId, 'metadata.json');
317
- await this.fileProcessor.writeFile(metadataPath, JSON.stringify(metadata, null, 2), 'utf8');
318
-
319
- // Update index
320
- if (this.index.attachments[fileId]) {
321
- this.index.attachments[fileId].active = metadata.active;
322
- await this.saveIndex();
323
- }
324
-
325
- this.logger?.info('Attachment active state toggled', { fileId, active: metadata.active });
326
-
327
- return metadata;
328
- } catch (error) {
329
- this.logger?.error('Error toggling attachment', { fileId, error: error.message });
330
- throw error;
331
- }
332
- }
333
-
334
- /**
335
- * Update attachment metadata
336
- * @param {string} fileId - File ID
337
- * @param {Object} updates - Fields to update
338
- * @returns {Promise<Object>} Updated metadata
339
- */
340
- async updateAttachment(fileId, updates) {
341
- try {
342
- const metadata = await this.getAttachment(fileId);
343
- if (!metadata) {
344
- throw new Error(`Attachment not found: ${fileId}`);
345
- }
346
-
347
- // Allow only safe updates
348
- const allowedFields = ['fileName', 'active'];
349
- for (const field of allowedFields) {
350
- if (updates[field] !== undefined) {
351
- metadata[field] = updates[field];
352
- }
353
- }
354
-
355
- metadata.lastModified = new Date().toISOString();
356
-
357
- // Save updated metadata
358
- const metadataPath = path.join(ATTACHMENTS_DIR, metadata.agentId, fileId, 'metadata.json');
359
- await this.fileProcessor.writeFile(metadataPath, JSON.stringify(metadata, null, 2), 'utf8');
360
-
361
- // Update index
362
- if (this.index.attachments[fileId]) {
363
- if (updates.fileName) {
364
- this.index.attachments[fileId].fileName = updates.fileName;
365
- }
366
- if (updates.active !== undefined) {
367
- this.index.attachments[fileId].active = updates.active;
368
- }
369
- await this.saveIndex();
370
- }
371
-
372
- this.logger?.info('Attachment updated', { fileId, updates });
373
-
374
- return metadata;
375
- } catch (error) {
376
- this.logger?.error('Error updating attachment', { fileId, error: error.message });
377
- throw error;
378
- }
379
- }
380
-
381
- /**
382
- * Delete attachment (with reference counting)
383
- * @param {string} fileId - File ID
384
- * @param {string} agentId - Agent ID requesting deletion
385
- * @returns {Promise<boolean>} true if deleted, false if still referenced
386
- */
387
- async deleteAttachment(fileId, agentId) {
388
- try {
389
- const metadata = await this.getAttachment(fileId);
390
- if (!metadata) {
391
- throw new Error(`Attachment not found: ${fileId}`);
392
- }
393
-
394
- // Remove agent from referencedBy
395
- metadata.referencedBy = metadata.referencedBy.filter(id => id !== agentId);
396
-
397
- // If still referenced by other agents, just update metadata
398
- if (metadata.referencedBy.length > 0) {
399
- const metadataPath = path.join(ATTACHMENTS_DIR, metadata.agentId, fileId, 'metadata.json');
400
- await this.fileProcessor.writeFile(metadataPath, JSON.stringify(metadata, null, 2), 'utf8');
401
-
402
- // Update index
403
- if (this.index.attachments[fileId]) {
404
- this.index.attachments[fileId].referencedBy = metadata.referencedBy;
405
- }
406
- if (this.index.agentRefs[agentId]) {
407
- this.index.agentRefs[agentId] = this.index.agentRefs[agentId].filter(id => id !== fileId);
408
- }
409
- await this.saveIndex();
410
-
411
- this.logger?.info('Attachment dereferenced', { fileId, agentId, remainingRefs: metadata.referencedBy.length });
412
- return false;
413
- }
414
-
415
- // No more references, delete physical files
416
- const attachmentDir = path.join(ATTACHMENTS_DIR, metadata.agentId, fileId);
417
- await this.fileProcessor.deleteDirectory(attachmentDir);
418
-
419
- // Remove from index
420
- delete this.index.attachments[fileId];
421
- if (this.index.agentRefs[agentId]) {
422
- this.index.agentRefs[agentId] = this.index.agentRefs[agentId].filter(id => id !== fileId);
423
- }
424
- await this.saveIndex();
425
-
426
- this.logger?.info('Attachment deleted', { fileId, agentId });
427
- return true;
428
- } catch (error) {
429
- this.logger?.error('Error deleting attachment', { fileId, agentId, error: error.message });
430
- throw error;
431
- }
432
- }
433
-
434
- /**
435
- * Delete all attachments for an agent
436
- * @param {string} agentId - Agent ID
437
- * @returns {Promise<Object>} { deleted: number, dereferenced: number }
438
- */
439
- async deleteAgentAttachments(agentId) {
440
- try {
441
- const fileIds = this.index.agentRefs[agentId] || [];
442
- let deleted = 0;
443
- let dereferenced = 0;
444
-
445
- for (const fileId of fileIds) {
446
- const wasDeleted = await this.deleteAttachment(fileId, agentId);
447
- if (wasDeleted) {
448
- deleted++;
449
- } else {
450
- dereferenced++;
451
- }
452
- }
453
-
454
- this.logger?.info('Agent attachments deleted', { agentId, deleted, dereferenced });
455
-
456
- return { deleted, dereferenced };
457
- } catch (error) {
458
- this.logger?.error('Error deleting agent attachments', { agentId, error: error.message });
459
- throw error;
460
- }
461
- }
462
-
463
- /**
464
- * Import attachment from another agent
465
- * @param {string} sourceFileId - Source file ID
466
- * @param {string} targetAgentId - Target agent ID
467
- * @returns {Promise<Object>} New attachment metadata
468
- */
469
- async importFromAgent(sourceFileId, targetAgentId) {
470
- try {
471
- const sourceMetadata = await this.getAttachment(sourceFileId);
472
- if (!sourceMetadata) {
473
- throw new Error(`Source attachment not found: ${sourceFileId}`);
474
- }
475
-
476
- // Add target agent to referencedBy
477
- if (!sourceMetadata.referencedBy.includes(targetAgentId)) {
478
- sourceMetadata.referencedBy.push(targetAgentId);
479
- }
480
-
481
- sourceMetadata.lastModified = new Date().toISOString();
482
- sourceMetadata.importedFrom = sourceMetadata.agentId;
483
-
484
- // Save updated metadata
485
- const metadataPath = path.join(ATTACHMENTS_DIR, sourceMetadata.agentId, sourceFileId, 'metadata.json');
486
- await this.fileProcessor.writeFile(metadataPath, JSON.stringify(sourceMetadata, null, 2), 'utf8');
487
-
488
- // Update index
489
- if (this.index.attachments[sourceFileId]) {
490
- this.index.attachments[sourceFileId].referencedBy = sourceMetadata.referencedBy;
491
- }
492
- if (!this.index.agentRefs[targetAgentId]) {
493
- this.index.agentRefs[targetAgentId] = [];
494
- }
495
- if (!this.index.agentRefs[targetAgentId].includes(sourceFileId)) {
496
- this.index.agentRefs[targetAgentId].push(sourceFileId);
497
- }
498
- await this.saveIndex();
499
-
500
- this.logger?.info('Attachment imported', { sourceFileId, targetAgentId });
501
-
502
- return sourceMetadata;
503
- } catch (error) {
504
- this.logger?.error('Error importing attachment', { sourceFileId, targetAgentId, error: error.message });
505
- throw error;
506
- }
507
- }
508
-
509
- /**
510
- * Get active attachments for an agent
511
- * @param {string} agentId - Agent ID
512
- * @returns {Promise<Array>} Array of active attachment metadata
513
- */
514
- async getActiveAttachments(agentId) {
515
- return await this.getAttachments(agentId, { active: true });
516
- }
517
-
518
- /**
519
- * Get attachment preview (first 1000 characters)
520
- * @param {string} fileId - File ID
521
- * @returns {Promise<string|null>} Preview text or null
522
- */
523
- async getAttachmentPreview(fileId) {
524
- try {
525
- const content = await this.getAttachmentContent(fileId);
526
- if (!content) {
527
- return null;
528
- }
529
-
530
- // For base64 images, return metadata instead of content
531
- if (content.startsWith('data:image')) {
532
- return '[Image content - base64 encoded]';
533
- }
534
-
535
- // Return first 1000 characters
536
- return content.length > 1000 ? content.substring(0, 1000) + '...' : content;
537
- } catch (error) {
538
- this.logger?.error('Error getting attachment preview', { fileId, error: error.message });
539
- return null;
540
- }
541
- }
542
- }
543
-
544
- export default FileAttachmentService;
1
+ const a0_0xef0fcf=a0_0x31cb;function a0_0x31cb(_0x38ead3,_0x423bd6){_0x38ead3=_0x38ead3-0x17c;const _0x50a2fb=a0_0x50a2();let _0x31cb85=_0x50a2fb[_0x38ead3];if(a0_0x31cb['ywDkFJ']===undefined){var _0x4edafa=function(_0x407e37){const _0x58c8ec='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x1b7561='',_0x4ca4de='';for(let _0x5e89af=0x0,_0x11f384,_0x31d69e,_0x352458=0x0;_0x31d69e=_0x407e37['charAt'](_0x352458++);~_0x31d69e&&(_0x11f384=_0x5e89af%0x4?_0x11f384*0x40+_0x31d69e:_0x31d69e,_0x5e89af++%0x4)?_0x1b7561+=String['fromCharCode'](0xff&_0x11f384>>(-0x2*_0x5e89af&0x6)):0x0){_0x31d69e=_0x58c8ec['indexOf'](_0x31d69e);}for(let _0x15e644=0x0,_0x173de4=_0x1b7561['length'];_0x15e644<_0x173de4;_0x15e644++){_0x4ca4de+='%'+('00'+_0x1b7561['charCodeAt'](_0x15e644)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x4ca4de);};a0_0x31cb['OSWEcU']=_0x4edafa,a0_0x31cb['DrumBv']={},a0_0x31cb['ywDkFJ']=!![];}const _0x5a802f=_0x50a2fb[0x0],_0x4138f3=_0x38ead3+_0x5a802f,_0x410139=a0_0x31cb['DrumBv'][_0x4138f3];return!_0x410139?(_0x31cb85=a0_0x31cb['OSWEcU'](_0x31cb85),a0_0x31cb['DrumBv'][_0x4138f3]=_0x31cb85):_0x31cb85=_0x410139,_0x31cb85;}(function(_0x500b95,_0x422d9b){const _0xd71b4e=a0_0x31cb,_0x14497e=_0x500b95();while(!![]){try{const _0x342fc7=-parseInt(_0xd71b4e(0x18e))/0x1+-parseInt(_0xd71b4e(0x1a5))/0x2*(-parseInt(_0xd71b4e(0x1c3))/0x3)+parseInt(_0xd71b4e(0x19c))/0x4+parseInt(_0xd71b4e(0x1aa))/0x5+parseInt(_0xd71b4e(0x1bf))/0x6*(parseInt(_0xd71b4e(0x19b))/0x7)+-parseInt(_0xd71b4e(0x190))/0x8+-parseInt(_0xd71b4e(0x18f))/0x9;if(_0x342fc7===_0x422d9b)break;else _0x14497e['push'](_0x14497e['shift']());}catch(_0x2f60ea){_0x14497e['push'](_0x14497e['shift']());}}}(a0_0x50a2,0xdc102));import a0_0x1b7561 from'path';import{fileURLToPath}from'url';import{randomUUID}from'crypto';import a0_0x4ca4de from'../utilities/fileProcessor.js';function a0_0x50a2(){const _0x40f079=['nJi4ndaXnuHjv2LfrG','Dg9Nz2XLqwn0AxzL','rxjYB3iGBg9HzgLUzYbPBMrLEa','BgvUz3rO','y29UDgvUDc50Ehq','Bwv0ywrHDgeUANnVBG','y3jLyxrLrgLYzwn0B3j5','zgvSzxrLrgLYzwn0B3j5','D3jPDgvgAwXL','DxbKyxrLqxr0ywnOBwvUDa','Bg9HzeLUzgv4','ywDLBNrjza','y29UDgvUDa','Aw5MBW','Bw9Kzq','Aw1Hz2u','zgf0ytPPBwfNzq','CMvMzxjLBMnLzej5','z2v0qxr0ywnOBwvUDenVBNrLBNq','rxjYB3iGz2v0DgLUzYbHDhrHy2HTzw50','rMLSzuf0DgfJAg1LBNrtzxj2AwnLigLUAxrPywXPEMvK','ndC3mZiZng5HCxDktG','Dg9ju09tDhjPBMC','qxr0ywnOBwvUDcbKzwXLDgvK','rMLSzsbUB3qGzM91BMq6ia','nMPryMPlzG','zxjYB3i','ChjVy2vZC0zPBgu','zMLSDgvY','Aw5JBhvKzxm','ywn0AxzL','w0LTywDLignVBNrLBNqGlsbIyxnLnJqGzw5JB2rLzf0','zMLSzuv4Axn0CW','DMfSAwrHDg9Y','CgfYC2u','zMLSzu5HBwu','CMvMzxjLBMnL','rxjYB3iGz2v0DgLUzYbHDhrHy2HTzw50CW','Bg9Nz2vY','zgvSzxrLqwDLBNrbDhrHy2HTzw50CW','rxjYB3iGzgvSzxrPBMCGywDLBNqGyxr0ywnOBwvUDhm','z2v0qxr0ywnOBwvUDa','C2L6zq','qxr0ywnOBwvUDcb1CgrHDgvK','mtqXmte0mejMuffwAG','mtC1mtaXnJzzvfrcvKG','nJuZotK0ng5yDeHlBa','zxjYB3jZ','C3rYAw5NAwz5','C2L6zuXLDMvS','y2fSy3vSyxrLsgfZAa','Aw5KzxG','ChvZAa','vMfSAwrHDgLVBIbMywLSzwq6ia','qxr0ywnOBwvUDcbHy3rPDMuGC3rHDguGDg9Nz2XLza','C3vIC3rYAw5N','zMLSzvbYB2nLC3nVCG','n0v5EKXMCa','nJm5mdm2nhDTC0DNtG','y29UDgvUDezPBgvoyw1L','AM9PBG','yxr0ywnOBwvUDhm','rxjYB3iGAw5PDgLHBgL6Aw5NiezPBgvbDhrHy2HTzw50u2vYDMLJzq','zxn0Aw1HDgvuB2TLBNm','zgLYBMfTzq','DxrMoa','rMLSzsb1CgXVywrLza','mtqYnty1mLn0AufNvq','ywDLBNrszwzZ','C2f2zuLUzgv4','Bw9KAwzPzwq','BwvZC2fNzq'];a0_0x50a2=function(){return _0x40f079;};return a0_0x50a2();}import a0_0x5e89af from'../utilities/attachmentValidator.js';const __filename=fileURLToPath(import.meta.url),__dirname=a0_0x1b7561[a0_0xef0fcf(0x1a2)](__filename),ATTACHMENTS_DIR=a0_0x1b7561[a0_0xef0fcf(0x19e)](process['cwd'](),'loxia-state','attachments'),INDEX_FILE=a0_0x1b7561['join'](ATTACHMENTS_DIR,'attachments-index.json');class FileAttachmentService{constructor(_0x11f384={},_0x31d69e=null){const _0x2a5555=a0_0xef0fcf;this['config']=_0x11f384,this[_0x2a5555(0x188)]=_0x31d69e,this[_0x2a5555(0x19a)]=new a0_0x4ca4de(_0x11f384,_0x31d69e),this['validator']=new a0_0x5e89af(_0x11f384,_0x31d69e),this['index']=null;}async['initialize'](){const _0x4eeb99=a0_0xef0fcf;try{await this['fileProcessor'][_0x4eeb99(0x1b0)](ATTACHMENTS_DIR),await this['loadIndex'](),this[_0x4eeb99(0x188)]?.[_0x4eeb99(0x1b7)](_0x4eeb99(0x1be),{'attachmentsDir':ATTACHMENTS_DIR});}catch(_0x352458){this['logger']?.[_0x4eeb99(0x17c)](_0x4eeb99(0x1a0),{'error':_0x352458['message']});throw _0x352458;}}async['loadIndex'](){const _0x24591b=a0_0xef0fcf;try{const _0x15e644=await this['fileProcessor'][_0x24591b(0x182)](INDEX_FILE);if(!_0x15e644)this['index']={'attachments':{},'agentRefs':{}},await this[_0x24591b(0x1a7)]();else{const _0x173de4=await this['fileProcessor']['readFile'](INDEX_FILE,_0x24591b(0x1a3));this[_0x24591b(0x195)]=JSON[_0x24591b(0x184)](_0x173de4);}return this['index'];}catch(_0x2e8c0c){return this[_0x24591b(0x188)]?.[_0x24591b(0x17c)](_0x24591b(0x1ac),{'error':_0x2e8c0c[_0x24591b(0x1a9)]}),this[_0x24591b(0x195)]={'attachments':{},'agentRefs':{}},this[_0x24591b(0x195)];}}async['saveIndex'](){const _0xf1a3d9=a0_0xef0fcf;try{await this['fileProcessor'][_0xf1a3d9(0x1b2)](INDEX_FILE,JSON[_0xf1a3d9(0x192)](this['index'],null,0x2),_0xf1a3d9(0x1a3));}catch(_0x13c332){this[_0xf1a3d9(0x188)]?.[_0xf1a3d9(0x17c)]('Error\x20saving\x20index',{'error':_0x13c332[_0xf1a3d9(0x1a9)]});throw _0x13c332;}}async['uploadFile']({agentId:_0x46efd4,filePath:_0x27d53a,mode:mode='content',fileName:fileName=null}){const _0x4948ff=a0_0xef0fcf;!this['index']&&await this['loadIndex']();try{const _0x224250=await this[_0x4948ff(0x19a)][_0x4948ff(0x182)](_0x27d53a);if(!_0x224250)throw new Error(_0x4948ff(0x1c2)+_0x27d53a);const _0x3a3408=await this['fileProcessor']['getFileStats'](_0x27d53a),_0x2742f1=fileName||a0_0x1b7561['basename'](_0x27d53a),_0x2c072b=a0_0x1b7561['extname'](_0x2742f1),_0x25b1ad=this['validator']['validate']({'fileName':_0x2742f1,'size':_0x3a3408[_0x4948ff(0x18c)],'mode':mode,'path':mode===_0x4948ff(0x186)?_0x27d53a:null});if(!_0x25b1ad['valid'])throw new Error(_0x4948ff(0x197)+_0x25b1ad[_0x4948ff(0x191)][_0x4948ff(0x19e)](',\x20'));const _0x53064b=randomUUID(),_0x364ed4=await this[_0x4948ff(0x19a)][_0x4948ff(0x194)](_0x27d53a),_0x4d13d4=this['validator']['getContentType'](_0x2742f1),_0x44d980=a0_0x1b7561[_0x4948ff(0x19e)](ATTACHMENTS_DIR,_0x46efd4,_0x53064b);await this[_0x4948ff(0x19a)][_0x4948ff(0x1b0)](_0x44d980);let _0x32d99e=0x0,_0x528dca=null;if(mode==='content'){const processResult=await this[_0x4948ff(0x19a)][_0x4948ff(0x17d)](_0x27d53a,_0x4d13d4),_0x1fc196=processResult['content'];if(_0x4d13d4==='text')_0x528dca='content.txt';else{if(_0x4d13d4===_0x4948ff(0x1b9))_0x528dca='content.base64';else _0x4d13d4==='pdf'&&(_0x528dca=_0x4948ff(0x1ae));}const _0x4eba23=a0_0x1b7561['join'](_0x44d980,_0x528dca);await this[_0x4948ff(0x19a)][_0x4948ff(0x1b2)](_0x4eba23,_0x1fc196,'utf8'),_0x32d99e=this[_0x4948ff(0x19a)][_0x4948ff(0x1a1)](_0x1fc196);}const _0x2fda4f={'fileId':_0x53064b,'agentId':_0x46efd4,'fileName':_0x2742f1,'originalPath':_0x27d53a,'fileType':this[_0x4948ff(0x183)]['getMimeType'](_0x2742f1),'fileExtension':_0x2c072b,'size':_0x3a3408[_0x4948ff(0x18c)],'mode':mode,'active':!![],'uploadedAt':new Date()[_0x4948ff(0x1c0)](),'lastModified':_0x3a3408[_0x4948ff(0x1a8)][_0x4948ff(0x1c0)](),'hash':_0x364ed4,'tokenEstimate':_0x32d99e,'contentType':_0x4d13d4,'contentFileName':_0x528dca,'warnings':_0x25b1ad['warnings'],'sizeLevel':_0x25b1ad[_0x4948ff(0x193)],'importedFrom':null,'referencedBy':[_0x46efd4]},_0x3d18ba=a0_0x1b7561[_0x4948ff(0x19e)](_0x44d980,_0x4948ff(0x1af));return await this['fileProcessor']['writeFile'](_0x3d18ba,JSON['stringify'](_0x2fda4f,null,0x2),_0x4948ff(0x1a3)),this[_0x4948ff(0x195)][_0x4948ff(0x19f)][_0x53064b]={'fileId':_0x53064b,'agentId':_0x46efd4,'fileName':_0x2742f1,'mode':mode,'active':_0x2fda4f['active'],'referencedBy':_0x2fda4f['referencedBy']},!this['index'][_0x4948ff(0x1a6)][_0x46efd4]&&(this[_0x4948ff(0x195)]['agentRefs'][_0x46efd4]=[]),this[_0x4948ff(0x195)][_0x4948ff(0x1a6)][_0x46efd4]['push'](_0x53064b),await this['saveIndex'](),this['logger']?.[_0x4948ff(0x1b7)](_0x4948ff(0x1a4),{'fileId':_0x53064b,'agentId':_0x46efd4,'fileName':_0x2742f1,'mode':mode}),_0x2fda4f;}catch(_0x1a4713){this[_0x4948ff(0x188)]?.['error']('Error\x20uploading\x20file',{'agentId':_0x46efd4,'filePath':_0x27d53a,'error':_0x1a4713[_0x4948ff(0x1a9)]});throw _0x1a4713;}}async['getAttachments'](_0x35b9be,_0x510940={}){const _0x3fdb5d=a0_0xef0fcf;!this[_0x3fdb5d(0x195)]&&await this['loadIndex']();try{const _0x5ce353=this['index']['agentRefs'][_0x35b9be]||[],_0x55b5f0=[];for(const _0x2d29e5 of _0x5ce353){const _0x5bbc28=await this[_0x3fdb5d(0x18b)](_0x2d29e5);if(_0x5bbc28){if(_0x510940[_0x3fdb5d(0x180)]!==undefined&&_0x5bbc28[_0x3fdb5d(0x180)]!==_0x510940[_0x3fdb5d(0x180)])continue;if(_0x510940[_0x3fdb5d(0x1b8)]&&_0x5bbc28[_0x3fdb5d(0x1b8)]!==_0x510940['mode'])continue;_0x55b5f0[_0x3fdb5d(0x196)](_0x5bbc28);}}return _0x55b5f0;}catch(_0x1cc2fc){this[_0x3fdb5d(0x188)]?.[_0x3fdb5d(0x17c)](_0x3fdb5d(0x187),{'agentId':_0x35b9be,'error':_0x1cc2fc[_0x3fdb5d(0x1a9)]});throw _0x1cc2fc;}}async['getAttachment'](_0x45c584){const _0x15ec6b=a0_0xef0fcf;!this['index']&&await this[_0x15ec6b(0x1b4)]();try{const _0x5ac371=this['index'][_0x15ec6b(0x19f)][_0x45c584];if(!_0x5ac371)return null;const _0x301b45=a0_0x1b7561[_0x15ec6b(0x19e)](ATTACHMENTS_DIR,_0x5ac371[_0x15ec6b(0x1b5)],_0x45c584,_0x15ec6b(0x1af)),_0x480eb2=await this[_0x15ec6b(0x19a)]['fileExists'](_0x301b45);if(!_0x480eb2)return this['logger']?.['warn']('Metadata\x20file\x20not\x20found',{'fileId':_0x45c584}),null;const _0x4aa535=await this['fileProcessor']['readFile'](_0x301b45,'utf8');return JSON[_0x15ec6b(0x184)](_0x4aa535);}catch(_0x23879f){return this[_0x15ec6b(0x188)]?.[_0x15ec6b(0x17c)](_0x15ec6b(0x1bd),{'fileId':_0x45c584,'error':_0x23879f['message']}),null;}}async[a0_0xef0fcf(0x1bc)](_0x339a46){const _0x2749de=a0_0xef0fcf;try{const _0x1d5ecc=await this['getAttachment'](_0x339a46);if(!_0x1d5ecc||_0x1d5ecc[_0x2749de(0x1b8)]!==_0x2749de(0x1b6))return null;const _0x306339=a0_0x1b7561[_0x2749de(0x19e)](ATTACHMENTS_DIR,_0x1d5ecc[_0x2749de(0x1b5)],_0x339a46,_0x1d5ecc[_0x2749de(0x19d)]),_0xdc54d8=await this['fileProcessor'][_0x2749de(0x182)](_0x306339);if(!_0xdc54d8)return null;return await this['fileProcessor']['readFile'](_0x306339,'utf8');}catch(_0x388d17){return this['logger']?.[_0x2749de(0x17c)]('Error\x20getting\x20attachment\x20content',{'fileId':_0x339a46,'error':_0x388d17['message']}),null;}}async[a0_0xef0fcf(0x1ab)](_0x427482){const _0x5a42fd=a0_0xef0fcf;try{const _0x1cfc0d=await this['getAttachment'](_0x427482);if(!_0x1cfc0d)throw new Error('Attachment\x20not\x20found:\x20'+_0x427482);_0x1cfc0d[_0x5a42fd(0x180)]=!_0x1cfc0d['active'],_0x1cfc0d['lastModified']=new Date()[_0x5a42fd(0x1c0)]();const _0x2b5b1a=a0_0x1b7561[_0x5a42fd(0x19e)](ATTACHMENTS_DIR,_0x1cfc0d[_0x5a42fd(0x1b5)],_0x427482,_0x5a42fd(0x1af));return await this['fileProcessor']['writeFile'](_0x2b5b1a,JSON['stringify'](_0x1cfc0d,null,0x2),'utf8'),this[_0x5a42fd(0x195)]['attachments'][_0x427482]&&(this['index'][_0x5a42fd(0x19f)][_0x427482][_0x5a42fd(0x180)]=_0x1cfc0d['active'],await this[_0x5a42fd(0x1a7)]()),this['logger']?.[_0x5a42fd(0x1b7)](_0x5a42fd(0x198),{'fileId':_0x427482,'active':_0x1cfc0d[_0x5a42fd(0x180)]}),_0x1cfc0d;}catch(_0x18c550){this['logger']?.[_0x5a42fd(0x17c)]('Error\x20toggling\x20attachment',{'fileId':_0x427482,'error':_0x18c550[_0x5a42fd(0x1a9)]});throw _0x18c550;}}async[a0_0xef0fcf(0x1b3)](_0x10fed7,_0x465798){const _0x16b584=a0_0xef0fcf;try{const _0x352f43=await this['getAttachment'](_0x10fed7);if(!_0x352f43)throw new Error('Attachment\x20not\x20found:\x20'+_0x10fed7);const _0x588415=['fileName',_0x16b584(0x180)];for(const _0x441530 of _0x588415){_0x465798[_0x441530]!==undefined&&(_0x352f43[_0x441530]=_0x465798[_0x441530]);}_0x352f43['lastModified']=new Date()['toISOString']();const _0x1fcc5c=a0_0x1b7561['join'](ATTACHMENTS_DIR,_0x352f43['agentId'],_0x10fed7,'metadata.json');return await this[_0x16b584(0x19a)]['writeFile'](_0x1fcc5c,JSON['stringify'](_0x352f43,null,0x2),'utf8'),this[_0x16b584(0x195)]['attachments'][_0x10fed7]&&(_0x465798['fileName']&&(this[_0x16b584(0x195)]['attachments'][_0x10fed7]['fileName']=_0x465798[_0x16b584(0x185)]),_0x465798[_0x16b584(0x180)]!==undefined&&(this['index'][_0x16b584(0x19f)][_0x10fed7]['active']=_0x465798[_0x16b584(0x180)]),await this['saveIndex']()),this[_0x16b584(0x188)]?.[_0x16b584(0x1b7)](_0x16b584(0x18d),{'fileId':_0x10fed7,'updates':_0x465798}),_0x352f43;}catch(_0x2c0326){this[_0x16b584(0x188)]?.['error']('Error\x20updating\x20attachment',{'fileId':_0x10fed7,'error':_0x2c0326[_0x16b584(0x1a9)]});throw _0x2c0326;}}async['deleteAttachment'](_0x117b2f,_0x579be3){const _0x174eac=a0_0xef0fcf;try{const _0x2f637f=await this['getAttachment'](_0x117b2f);if(!_0x2f637f)throw new Error('Attachment\x20not\x20found:\x20'+_0x117b2f);_0x2f637f['referencedBy']=_0x2f637f[_0x174eac(0x1bb)][_0x174eac(0x17e)](_0x2277e2=>_0x2277e2!==_0x579be3);if(_0x2f637f[_0x174eac(0x1bb)][_0x174eac(0x1ad)]>0x0){const _0x8fe128=a0_0x1b7561['join'](ATTACHMENTS_DIR,_0x2f637f['agentId'],_0x117b2f,'metadata.json');return await this[_0x174eac(0x19a)]['writeFile'](_0x8fe128,JSON[_0x174eac(0x192)](_0x2f637f,null,0x2),'utf8'),this[_0x174eac(0x195)][_0x174eac(0x19f)][_0x117b2f]&&(this[_0x174eac(0x195)]['attachments'][_0x117b2f]['referencedBy']=_0x2f637f[_0x174eac(0x1bb)]),this[_0x174eac(0x195)]['agentRefs'][_0x579be3]&&(this['index'][_0x174eac(0x1a6)][_0x579be3]=this['index'][_0x174eac(0x1a6)][_0x579be3][_0x174eac(0x17e)](_0x419761=>_0x419761!==_0x117b2f)),await this[_0x174eac(0x1a7)](),this['logger']?.[_0x174eac(0x1b7)]('Attachment\x20dereferenced',{'fileId':_0x117b2f,'agentId':_0x579be3,'remainingRefs':_0x2f637f['referencedBy'][_0x174eac(0x1ad)]}),![];}const _0x22c64c=a0_0x1b7561[_0x174eac(0x19e)](ATTACHMENTS_DIR,_0x2f637f['agentId'],_0x117b2f);return await this[_0x174eac(0x19a)][_0x174eac(0x1b1)](_0x22c64c),delete this['index'][_0x174eac(0x19f)][_0x117b2f],this[_0x174eac(0x195)][_0x174eac(0x1a6)][_0x579be3]&&(this['index'][_0x174eac(0x1a6)][_0x579be3]=this['index']['agentRefs'][_0x579be3][_0x174eac(0x17e)](_0x4ecd61=>_0x4ecd61!==_0x117b2f)),await this[_0x174eac(0x1a7)](),this[_0x174eac(0x188)]?.[_0x174eac(0x1b7)](_0x174eac(0x1c1),{'fileId':_0x117b2f,'agentId':_0x579be3}),!![];}catch(_0x54cf88){this[_0x174eac(0x188)]?.['error']('Error\x20deleting\x20attachment',{'fileId':_0x117b2f,'agentId':_0x579be3,'error':_0x54cf88[_0x174eac(0x1a9)]});throw _0x54cf88;}}async[a0_0xef0fcf(0x189)](_0x104a5b){const _0x4b5a55=a0_0xef0fcf;try{const _0x27b63b=this['index']['agentRefs'][_0x104a5b]||[];let _0x11b92b=0x0,_0x253439=0x0;for(const _0x34c83c of _0x27b63b){const _0x2ce0fa=await this['deleteAttachment'](_0x34c83c,_0x104a5b);_0x2ce0fa?_0x11b92b++:_0x253439++;}return this[_0x4b5a55(0x188)]?.['info']('Agent\x20attachments\x20deleted',{'agentId':_0x104a5b,'deleted':_0x11b92b,'dereferenced':_0x253439}),{'deleted':_0x11b92b,'dereferenced':_0x253439};}catch(_0x402959){this[_0x4b5a55(0x188)]?.['error'](_0x4b5a55(0x18a),{'agentId':_0x104a5b,'error':_0x402959[_0x4b5a55(0x1a9)]});throw _0x402959;}}async['importFromAgent'](_0x211d78,_0x3ef91a){const _0x2389e7=a0_0xef0fcf;try{const _0x186d3b=await this['getAttachment'](_0x211d78);if(!_0x186d3b)throw new Error('Source\x20attachment\x20not\x20found:\x20'+_0x211d78);!_0x186d3b[_0x2389e7(0x1bb)][_0x2389e7(0x17f)](_0x3ef91a)&&_0x186d3b[_0x2389e7(0x1bb)]['push'](_0x3ef91a);_0x186d3b['lastModified']=new Date()['toISOString'](),_0x186d3b['importedFrom']=_0x186d3b['agentId'];const _0x493c5e=a0_0x1b7561[_0x2389e7(0x19e)](ATTACHMENTS_DIR,_0x186d3b['agentId'],_0x211d78,_0x2389e7(0x1af));return await this['fileProcessor'][_0x2389e7(0x1b2)](_0x493c5e,JSON[_0x2389e7(0x192)](_0x186d3b,null,0x2),'utf8'),this[_0x2389e7(0x195)]['attachments'][_0x211d78]&&(this[_0x2389e7(0x195)]['attachments'][_0x211d78][_0x2389e7(0x1bb)]=_0x186d3b[_0x2389e7(0x1bb)]),!this['index'][_0x2389e7(0x1a6)][_0x3ef91a]&&(this[_0x2389e7(0x195)][_0x2389e7(0x1a6)][_0x3ef91a]=[]),!this[_0x2389e7(0x195)]['agentRefs'][_0x3ef91a][_0x2389e7(0x17f)](_0x211d78)&&this['index']['agentRefs'][_0x3ef91a]['push'](_0x211d78),await this[_0x2389e7(0x1a7)](),this['logger']?.['info']('Attachment imported',{'sourceFileId':_0x211d78,'targetAgentId':_0x3ef91a}),_0x186d3b;}catch(_0x189320){this['logger']?.['error']('Error importing attachment',{'sourceFileId':_0x211d78,'targetAgentId':_0x3ef91a,'error':_0x189320['message']});throw _0x189320;}}async['getActiveAttachments'](_0xe1a951){return await this['getAttachments'](_0xe1a951,{'active':!![]});}async['getAttachmentPreview'](_0x3ea7d2){const _0x423b97=a0_0xef0fcf;try{const _0x2e546f=await this['getAttachmentContent'](_0x3ea7d2);if(!_0x2e546f)return null;if(_0x2e546f['startsWith'](_0x423b97(0x1ba)))return _0x423b97(0x181);return _0x2e546f['length']>0x3e8?_0x2e546f[_0x423b97(0x199)](0x0,0x3e8)+'...':_0x2e546f;}catch(_0xe7b1d9){return this[_0x423b97(0x188)]?.[_0x423b97(0x17c)]('Error\x20getting\x20attachment\x20preview',{'fileId':_0x3ea7d2,'error':_0xe7b1d9[_0x423b97(0x1a9)]}),null;}}}export default FileAttachmentService;