@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,1246 +1 @@
1
- /**
2
- * TagParser - Utility for parsing XML-style tags and JSON tool commands
3
- *
4
- * Purpose:
5
- * - Parse XML-style tool commands from agent messages
6
- * - Extract parameters from tag-based format
7
- * - Support for nested tags and attributes
8
- * - JSON tool command parsing
9
- * - Agent redirect parsing
10
- */
11
-
12
- import {
13
- AGENT_REDIRECT_ATTRIBUTES
14
- } from './constants.js';
15
- import {
16
- TOOL_IDS,
17
- COMMAND_FORMATS,
18
- JSON_STRUCTURES,
19
- identifyJsonStructure,
20
- getToolIdFromAction,
21
- isValidToolId
22
- } from './toolConstants.js';
23
-
24
- class TagParser {
25
- constructor() {
26
- // Tag parsing patterns
27
- this.patterns = {
28
- toolCommand: /<tool-command>(.*?)<\/tool-command>/gs,
29
- tool: /<tool\s+([^>]*)>(.*?)<\/tool>/gs,
30
- parameter: /<([^>\s]+)(?:\s+([^>]*))?>(((?!<\/\1>)[\s\S])*)<\/\1>/g,
31
- attribute: /([\w-]+)=["']([^"']*)["']/g,
32
- agentRedirect: /\[agent-redirect\s+([^\]]*)\](.*?)\[\/agent-redirect\]/gs,
33
- jsonBlock: /```json\s*(\{[\s\S]*?\})\s*```/g,
34
- // Also match plain JSON objects on their own line(s) as fallback
35
- plainJson: /^(\{(?:[^{}]|(?:\{[^{}]*\}))*\})$/gm
36
- };
37
- }
38
-
39
- /**
40
- * Decode HTML entities that might be present in tool content
41
- * @param {string} text - Text that might contain HTML entities
42
- * @returns {string} Decoded text
43
- */
44
- decodeHtmlEntities(text) {
45
- const entityMap = {
46
- '&lt;': '<',
47
- '&gt;': '>',
48
- '&amp;': '&',
49
- '&quot;': '"',
50
- '&#x27;': "'",
51
- '&#x2F;': '/',
52
- '&#39;': "'",
53
- '&#47;': '/'
54
- };
55
-
56
- return text.replace(/&(?:lt|gt|amp|quot|#x27|#x2F|#39|#47);/g, match => entityMap[match] || match);
57
- }
58
-
59
- /**
60
- * Extract tool commands from message content
61
- * @param {string} content - Message content to parse
62
- * @returns {Array} Array of parsed tool commands
63
- */
64
- extractToolCommands(content) {
65
- const commands = [];
66
-
67
- // Decode HTML entities that might be present in the content
68
- const decodedContent = this.decodeHtmlEntities(content);
69
-
70
- // PHASE 1: Extract explicit tool invocations (OUTER layer identification)
71
- // These use explicit markers: <toolname>, [tool id=""], or ```json
72
- const xmlCommands = this.extractXMLToolCommands(decodedContent);
73
- commands.push(...xmlCommands);
74
-
75
- // PHASE 2: Extract JSON code blocks (also OUTER layer, explicit)
76
- // Extract these BEFORE sanitization so we don't lose them
77
- const jsonCodeBlockCommands = this.extractJSONCodeBlocks(decodedContent);
78
- commands.push(...jsonCodeBlockCommands);
79
-
80
- // PHASE 3: Sanitize content by removing already-extracted invocations
81
- // This prevents INNER payload from being misinterpreted as new tool invocations
82
- const sanitizedContent = this.removeToolInvocationBlocks(decodedContent);
83
-
84
- // PHASE 4: Extract plain JSON (fallback, only from sanitized content)
85
- // This should rarely find anything if agents follow the ```json block convention
86
- const plainJsonCommands = this.extractPlainJSON(sanitizedContent);
87
- commands.push(...plainJsonCommands);
88
-
89
- return commands;
90
- }
91
-
92
- /**
93
- * Remove content inside tool invocation blocks to prevent false JSON detection
94
- *
95
- * ARCHITECTURAL PRINCIPLE (OUTER-INNER HIERARCHY):
96
- * - OUTER layer (message level): Tool identification
97
- * - INNER layer (payload level): Action/data for the tool
98
- *
99
- * Tool invocations appear at MESSAGE LEVEL using explicit markers:
100
- * - XML: <toolname>...</toolname> or [tool id="..."]...[/tool]
101
- * - JSON: ```json {"toolId": "..."} ```
102
- *
103
- * Content INSIDE these markers is PAYLOAD, not new tool invocations.
104
- *
105
- * This method removes:
106
- * - Direct tool tags: <taskmanager>...</taskmanager>, <filesystem>...</filesystem>, etc.
107
- * - Bracket notation: [tool id="filesystem"]...[/tool]
108
- * - JSON code blocks: ```json ... ```
109
- *
110
- * This prevents:
111
- * - File content like {"type": "image/png"} inside <write> tags from being detected
112
- * - Duplicate extraction of the same JSON block
113
- *
114
- * @param {string} content - Content to sanitize
115
- * @returns {string} Content with tool invocation blocks removed/replaced with placeholders
116
- * @private
117
- */
118
- removeToolInvocationBlocks(content) {
119
- let sanitized = content;
120
-
121
- // Remove JSON code blocks first (to prevent duplicate extraction)
122
- let jsonBlockPosition = 0;
123
- while (jsonBlockPosition < sanitized.length) {
124
- const startMarker = '```json';
125
- const endMarker = '```';
126
-
127
- const startIndex = sanitized.indexOf(startMarker, jsonBlockPosition);
128
- if (startIndex === -1) break;
129
-
130
- const contentStart = startIndex + startMarker.length;
131
- const endIndex = sanitized.indexOf(endMarker, contentStart);
132
- if (endIndex === -1) break;
133
-
134
- // Replace JSON code block with placeholder
135
- const before = sanitized.substring(0, startIndex);
136
- const after = sanitized.substring(endIndex + endMarker.length);
137
- sanitized = before + '[JSON_CODE_BLOCK_REMOVED]' + after;
138
-
139
- jsonBlockPosition = startIndex + '[JSON_CODE_BLOCK_REMOVED]'.length;
140
- }
141
-
142
- // List of known tool names (matches extractDirectToolTags)
143
- const toolNames = [
144
- 'taskmanager', 'filesystem', 'terminal', 'browser',
145
- 'agentcommunication', 'jobdone', 'agentdelay', 'image-gen'
146
- ];
147
-
148
- // Remove direct tool tags like <filesystem>...</filesystem>
149
- for (const toolName of toolNames) {
150
- const openTag = `<${toolName}>`;
151
- const closeTag = `</${toolName}>`;
152
-
153
- let position = 0;
154
- while (position < sanitized.length) {
155
- const openIndex = sanitized.indexOf(openTag, position);
156
- if (openIndex === -1) break;
157
-
158
- const closeIndex = sanitized.indexOf(closeTag, openIndex + openTag.length);
159
- if (closeIndex === -1) break;
160
-
161
- // Replace the entire tool block with a placeholder to preserve message structure
162
- // This allows JSON outside tool blocks to still be detected
163
- const before = sanitized.substring(0, openIndex);
164
- const after = sanitized.substring(closeIndex + closeTag.length);
165
- sanitized = before + `[XML_TOOL_REMOVED:${toolName}]` + after;
166
-
167
- position = openIndex + `[XML_TOOL_REMOVED:${toolName}]`.length;
168
- }
169
- }
170
-
171
- // Remove bracket notation tool blocks: [tool id="..."]...[/tool]
172
- // Use a simple loop to avoid regex complexity
173
- let bracketPosition = 0;
174
- while (bracketPosition < sanitized.length) {
175
- const openMarker = '[tool id="';
176
- const openIndex = sanitized.indexOf(openMarker, bracketPosition);
177
- if (openIndex === -1) break;
178
-
179
- // Find the closing quote to extract tool ID
180
- const quoteStart = openIndex + openMarker.length;
181
- const quoteEnd = sanitized.indexOf('"', quoteStart);
182
- if (quoteEnd === -1) break;
183
-
184
- const toolId = sanitized.substring(quoteStart, quoteEnd);
185
-
186
- // Find the closing ] of the opening tag
187
- const openTagEnd = sanitized.indexOf(']', quoteEnd);
188
- if (openTagEnd === -1) break;
189
-
190
- // Find the closing [/tool]
191
- const closeMarker = '[/tool]';
192
- const closeIndex = sanitized.indexOf(closeMarker, openTagEnd);
193
- if (closeIndex === -1) break;
194
-
195
- // Replace the bracket tool block with placeholder
196
- const before = sanitized.substring(0, openIndex);
197
- const after = sanitized.substring(closeIndex + closeMarker.length);
198
- sanitized = before + `[BRACKET_TOOL_REMOVED:${toolId}]` + after;
199
-
200
- bracketPosition = openIndex + `[BRACKET_TOOL_REMOVED:${toolId}]`.length;
201
- }
202
-
203
- return sanitized;
204
- }
205
-
206
- /**
207
- * Extract XML-style tool commands
208
- * @param {string} content - Content to parse
209
- * @returns {Array} Array of parsed XML tool commands
210
- */
211
- extractXMLToolCommands(content) {
212
- const commands = [];
213
-
214
- // Find all tool-command blocks
215
- const toolCommandBlocks = this.matchAll(content, this.patterns.toolCommand);
216
-
217
- for (const block of toolCommandBlocks) {
218
- const blockContent = block.groups[1];
219
-
220
- // Extract individual tool elements within the block
221
- const tools = this.matchAll(blockContent, this.patterns.tool);
222
-
223
- for (const tool of tools) {
224
- const attributes = this.parseAttributes(tool.groups[1]);
225
- const toolContent = tool.groups[2];
226
-
227
- const command = {
228
- type: COMMAND_FORMATS.XML,
229
- toolId: attributes.id,
230
- attributes,
231
- parameters: this.parseXMLParameters(toolContent),
232
- rawContent: tool.match.trim(),
233
- blockContent: block.match.trim()
234
- };
235
-
236
- commands.push(command);
237
- }
238
- }
239
-
240
- // Extract direct tool tags (e.g., <taskmanager>, <filesystem>)
241
- const directToolTags = this.extractDirectToolTags(content);
242
- commands.push(...directToolTags);
243
-
244
- // Extract bracket notation (e.g., [tool id="filesystem"]...[/tool])
245
- const bracketNotationTools = this.extractBracketNotationTools(content);
246
- commands.push(...bracketNotationTools);
247
-
248
- return commands;
249
- }
250
-
251
- /**
252
- * Extract direct tool tags like <taskmanager>, <filesystem>, etc.
253
- * @param {string} content - Content to parse
254
- * @returns {Array} Array of parsed direct tool commands
255
- */
256
- extractDirectToolTags(content) {
257
- const commands = [];
258
- const toolNames = ['taskmanager', 'filesystem', 'terminal', 'browser', 'agentcommunication', 'jobdone', 'agentdelay', 'image-gen'];
259
-
260
- for (const toolName of toolNames) {
261
- const toolCommands = this.extractToolByName(content, toolName);
262
- commands.push(...toolCommands);
263
- }
264
-
265
- return commands;
266
- }
267
-
268
- /**
269
- * Extract bracket notation tool commands like [tool id="filesystem"]...[/tool]
270
- * @param {string} content - Content to parse
271
- * @returns {Array} Array of parsed bracket notation tool commands
272
- */
273
- extractBracketNotationTools(content) {
274
- const commands = [];
275
- const openMarker = '[tool id="';
276
- const closeMarker = '[/tool]';
277
-
278
- let position = 0;
279
-
280
- while (position < content.length) {
281
- // Find opening marker
282
- const openIndex = content.indexOf(openMarker, position);
283
- if (openIndex === -1) break;
284
-
285
- // Find the closing quote to extract tool ID
286
- const quoteStart = openIndex + openMarker.length;
287
- const quoteEnd = content.indexOf('"', quoteStart);
288
- if (quoteEnd === -1) break;
289
-
290
- const toolId = content.substring(quoteStart, quoteEnd);
291
-
292
- // Find the closing ] of the opening tag
293
- const openTagEnd = content.indexOf(']', quoteEnd);
294
- if (openTagEnd === -1) break;
295
-
296
- // Find the closing [/tool]
297
- const closeIndex = content.indexOf(closeMarker, openTagEnd);
298
- if (closeIndex === -1) break;
299
-
300
- // Extract tool content between the tags
301
- const toolContent = content.substring(openTagEnd + 1, closeIndex);
302
- const fullMatch = content.substring(openIndex, closeIndex + closeMarker.length);
303
-
304
- console.log(`TagParser DEBUG: extractBracketNotationTools - found ${toolId} tool`);
305
-
306
- const command = {
307
- type: COMMAND_FORMATS.XML,
308
- toolId: toolId,
309
- attributes: {},
310
- parameters: this.parseXMLParameters(toolContent),
311
- rawContent: fullMatch.trim(),
312
- blockContent: fullMatch.trim()
313
- };
314
-
315
- commands.push(command);
316
- position = closeIndex + closeMarker.length;
317
- }
318
-
319
- return commands;
320
- }
321
-
322
- /**
323
- * Extract tool tags by name using string functions
324
- * @param {string} content - Content to search
325
- * @param {string} toolName - Tool name to extract (e.g., 'taskmanager')
326
- * @returns {Array} Array of extracted tool commands
327
- */
328
- extractToolByName(content, toolName) {
329
- const commands = [];
330
- const openTag = `<${toolName}>`;
331
- const closeTag = `</${toolName}>`;
332
-
333
- let position = 0;
334
-
335
- while (position < content.length) {
336
- const openTagStart = content.indexOf(openTag, position);
337
- if (openTagStart === -1) break;
338
-
339
- const openTagEnd = openTagStart + openTag.length;
340
- const closeTagStart = content.indexOf(closeTag, openTagEnd);
341
-
342
- if (closeTagStart === -1) {
343
- position = openTagEnd;
344
- continue;
345
- }
346
-
347
- const toolContent = content.substring(openTagEnd, closeTagStart);
348
- const fullMatch = content.substring(openTagStart, closeTagStart + closeTag.length);
349
-
350
- console.log(`TagParser DEBUG: extractToolByName - found ${toolName} tool`);
351
-
352
- const command = {
353
- type: COMMAND_FORMATS.XML,
354
- toolId: toolName,
355
- attributes: {},
356
- parameters: this.parseXMLParameters(toolContent),
357
- rawContent: fullMatch.trim(),
358
- blockContent: fullMatch.trim()
359
- };
360
-
361
- commands.push(command);
362
- position = closeTagStart + closeTag.length;
363
- }
364
-
365
- return commands;
366
- }
367
-
368
- /**
369
- * Extract JSON-style tool commands
370
- * @param {string} content - Content to parse
371
- * @returns {Array} Array of parsed JSON tool commands
372
- */
373
- extractJSONToolCommands(content) {
374
- const commands = [];
375
-
376
- // Method 1: Find JSON in markdown code blocks (preferred format)
377
- commands.push(...this.extractJSONCodeBlocks(content));
378
-
379
- // Method 2: Find plain JSON objects (fallback for agents that don't use code blocks)
380
- commands.push(...this.extractPlainJSON(content));
381
-
382
- return commands;
383
- }
384
-
385
- /**
386
- * Extract JSON from markdown code blocks using string functions
387
- * @private
388
- */
389
- extractJSONCodeBlocks(content) {
390
- const commands = [];
391
- let searchIndex = 0;
392
-
393
- while (true) {
394
- // Find opening marker
395
- const startMarker = '```json';
396
- const endMarker = '```';
397
-
398
- const startIndex = content.indexOf(startMarker, searchIndex);
399
- if (startIndex === -1) break;
400
-
401
- // Find closing marker
402
- const contentStart = startIndex + startMarker.length;
403
- const endIndex = content.indexOf(endMarker, contentStart);
404
- if (endIndex === -1) break;
405
-
406
- // Extract JSON content
407
- const jsonString = content.substring(contentStart, endIndex).trim();
408
-
409
- try {
410
- const jsonData = JSON.parse(jsonString);
411
-
412
- if (this.isToolCommandJSON(jsonData)) {
413
- // ARCHITECTURAL PRINCIPLE: Use OUTER layer (toolId) for tool identification
414
- const toolId = jsonData.toolId || jsonData.tool;
415
-
416
- // Skip if no explicit outer tool identifier
417
- if (!toolId || toolId === 'unknown') {
418
- console.log('TagParser DEBUG: Skipping JSON block - missing explicit toolId');
419
- searchIndex = endIndex + endMarker.length;
420
- continue;
421
- }
422
-
423
- const command = {
424
- type: COMMAND_FORMATS.JSON,
425
- toolId: toolId,
426
- parameters: jsonData.parameters || jsonData.actions || {},
427
- actions: jsonData.actions,
428
- rawContent: content.substring(startIndex, endIndex + endMarker.length),
429
- jsonData
430
- };
431
-
432
- commands.push(command);
433
- }
434
-
435
- // Handle toolCommands array format
436
- if (jsonData.toolCommands && Array.isArray(jsonData.toolCommands)) {
437
- for (const toolCommand of jsonData.toolCommands) {
438
- if (this.isToolCommandJSON(toolCommand)) {
439
- // ARCHITECTURAL PRINCIPLE: Use OUTER layer (toolId) for tool identification
440
- const toolId = toolCommand.toolId || toolCommand.tool;
441
-
442
- // Skip if no explicit outer tool identifier
443
- if (!toolId || toolId === 'unknown') {
444
- console.log('TagParser DEBUG: Skipping toolCommand - missing explicit toolId');
445
- continue;
446
- }
447
-
448
- const command = {
449
- type: COMMAND_FORMATS.JSON,
450
- toolId: toolId,
451
- parameters: toolCommand.parameters || toolCommand.actions || {},
452
- actions: toolCommand.actions,
453
- rawContent: JSON.stringify(toolCommand, null, 2),
454
- jsonData: toolCommand
455
- };
456
-
457
- commands.push(command);
458
- }
459
- }
460
- }
461
-
462
- } catch (error) {
463
- // Invalid JSON, skip this block
464
- }
465
-
466
- searchIndex = endIndex + endMarker.length;
467
- }
468
-
469
- return commands;
470
- }
471
-
472
- /**
473
- * Extract plain JSON objects using string functions
474
- * @private
475
- */
476
- extractPlainJSON(content) {
477
- const commands = [];
478
- const lines = content.split('\n');
479
-
480
- for (let i = 0; i < lines.length; i++) {
481
- const line = lines[i].trim();
482
-
483
- // Skip if line doesn't start with {
484
- if (!line.startsWith('{')) continue;
485
-
486
- // Try to find complete JSON object
487
- let jsonString = '';
488
- let braceCount = 0;
489
- let foundComplete = false;
490
-
491
- // Start from current line and look for complete JSON
492
- for (let j = i; j < lines.length; j++) {
493
- const currentLine = lines[j].trim();
494
- jsonString += (j > i ? '\n' : '') + currentLine;
495
-
496
- // Count braces to find complete object
497
- for (const char of currentLine) {
498
- if (char === '{') braceCount++;
499
- if (char === '}') braceCount--;
500
- if (braceCount === 0 && char === '}') {
501
- foundComplete = true;
502
- break;
503
- }
504
- }
505
-
506
- if (foundComplete) break;
507
- }
508
-
509
- if (!foundComplete) continue;
510
-
511
- try {
512
- const jsonData = JSON.parse(jsonString);
513
-
514
- // ARCHITECTURAL PRINCIPLE: Use OUTER layer for tool identification
515
- // Only parse INNER content (actions, type) if OUTER identifier missing
516
- // This follows the layered invocation hierarchy:
517
- // OUTER (message level): Tool identification via "toolId"
518
- // INNER (payload level): Action specification via "type"
519
-
520
- // Check if this JSON looks like a tool command
521
- if (this.isToolCommandJSON(jsonData) ||
522
- (jsonData.actions && Array.isArray(jsonData.actions)) ||
523
- (jsonData.type && typeof jsonData.type === 'string')) {
524
-
525
- // CRITICAL: Use OUTER identifier first, only infer from INNER as fallback
526
- const toolId = jsonData.toolId || jsonData.tool || this.inferToolFromActions(jsonData);
527
-
528
- // Skip if we couldn't determine a valid tool
529
- if (!toolId || toolId === 'unknown') {
530
- console.log('TagParser DEBUG: Skipping plain JSON - could not determine valid toolId');
531
- continue;
532
- }
533
-
534
- const command = {
535
- type: COMMAND_FORMATS.JSON_PLAIN,
536
- toolId: toolId,
537
- parameters: jsonData.parameters || jsonData,
538
- actions: jsonData.actions,
539
- rawContent: jsonString,
540
- jsonData,
541
- warning: 'Plain JSON detected - should use ```json blocks'
542
- };
543
-
544
- commands.push(command);
545
- }
546
-
547
- } catch (error) {
548
- // Invalid JSON, skip
549
- continue;
550
- }
551
- }
552
-
553
- return commands;
554
- }
555
-
556
- /**
557
- * Infer tool ID from JSON structure
558
- * Uses the constants-based approach for deterministic tool identification
559
- * @private
560
- */
561
- inferToolFromActions(jsonData) {
562
- const structure = identifyJsonStructure(jsonData);
563
-
564
- switch (structure) {
565
- case JSON_STRUCTURES.STANDARD:
566
- // Already has toolId
567
- return jsonData.toolId || 'unknown';
568
-
569
- case JSON_STRUCTURES.ACTIONS_ARRAY:
570
- // Get tool from first action type
571
- if (jsonData.actions && jsonData.actions.length > 0) {
572
- const firstAction = jsonData.actions[0];
573
- const toolId = getToolIdFromAction(firstAction.type);
574
- return toolId || 'unknown';
575
- }
576
- break;
577
-
578
- case JSON_STRUCTURES.DIRECT_ACTION:
579
- // Get tool from type field
580
- const toolId = getToolIdFromAction(jsonData.type);
581
- return toolId || 'unknown';
582
-
583
- case JSON_STRUCTURES.TOOL_COMMANDS:
584
- // Get from first command
585
- if (jsonData.toolCommands && jsonData.toolCommands.length > 0) {
586
- return this.inferToolFromActions(jsonData.toolCommands[0]);
587
- }
588
- break;
589
- }
590
-
591
- return 'unknown';
592
- }
593
-
594
- /**
595
- * Extract agent redirects from content
596
- * @param {string} content - Content to parse
597
- * @returns {Array} Array of parsed agent redirects
598
- */
599
- extractAgentRedirects(content) {
600
- const redirects = [];
601
-
602
- const matches = this.matchAll(content, this.patterns.agentRedirect);
603
-
604
- for (const match of matches) {
605
- const attributeString = match.groups[1];
606
- const messageContent = match.groups[2].trim();
607
-
608
- const attributes = this.parseAttributes(attributeString);
609
-
610
- const redirect = {
611
- to: attributes.to,
612
- content: messageContent,
613
- urgent: attributes[AGENT_REDIRECT_ATTRIBUTES.URGENT] === 'true',
614
- requiresResponse: attributes[AGENT_REDIRECT_ATTRIBUTES.REQUIRES_RESPONSE] === 'true',
615
- context: attributes[AGENT_REDIRECT_ATTRIBUTES.CONTEXT],
616
- rawMatch: match.match
617
- };
618
-
619
- // Add any additional attributes
620
- for (const [key, value] of Object.entries(attributes)) {
621
- if (!['to', AGENT_REDIRECT_ATTRIBUTES.URGENT, AGENT_REDIRECT_ATTRIBUTES.REQUIRES_RESPONSE, AGENT_REDIRECT_ATTRIBUTES.CONTEXT].includes(key)) {
622
- redirect[key] = value;
623
- }
624
- }
625
-
626
- redirects.push(redirect);
627
- }
628
-
629
- return redirects;
630
- }
631
-
632
- /**
633
- * Parse XML parameters from tool content
634
- * @param {string} content - Tool content to parse
635
- * @returns {Object} Parsed parameters
636
- */
637
- parseXMLParameters(content) {
638
- const parameters = {};
639
-
640
- console.log('TagParser DEBUG: parseXMLParameters - content length:', content.length);
641
-
642
- let position = 0;
643
- let foundCount = 0;
644
-
645
- // Look for opening tags like <write>, <read>, etc.
646
- while (position < content.length) {
647
- const openTagStart = content.indexOf('<', position);
648
- if (openTagStart === -1) break;
649
-
650
- const openTagEnd = content.indexOf('>', openTagStart);
651
- if (openTagEnd === -1) break;
652
-
653
- // Extract the full opening tag
654
- const openTag = content.substring(openTagStart, openTagEnd + 1);
655
-
656
- // Parse tag name and attributes from the opening tag
657
- const spaceIndex = openTag.indexOf(' ');
658
- const tagName = spaceIndex > 0
659
- ? openTag.substring(1, spaceIndex)
660
- : openTag.substring(1, openTag.length - 1);
661
-
662
- const isValid = this.isValidXmlTagName(tagName);
663
-
664
- // Skip malformed tags or content that looks like code
665
- if (tagName.includes('/') || !tagName || !this.isValidXmlTagName(tagName)) {
666
- position = openTagEnd + 1;
667
- continue;
668
- }
669
-
670
- // Check if this is a self-closing tag (ends with />)
671
- const isSelfClosing = openTag.endsWith('/>');
672
-
673
- let tagContent = '';
674
- let closingTagStart = openTagEnd;
675
-
676
- if (isSelfClosing) {
677
- // Self-closing tag has no content
678
- tagContent = '';
679
- closingTagStart = openTagEnd; // Position right after the self-closing tag
680
- } else {
681
- // Look for the closing tag
682
- const closingTag = `</${tagName}>`;
683
- closingTagStart = content.indexOf(closingTag, openTagEnd + 1);
684
-
685
- if (closingTagStart === -1) {
686
- position = openTagEnd + 1;
687
- continue;
688
- }
689
-
690
- // Extract the content between tags
691
- tagContent = content.substring(openTagEnd + 1, closingTagStart);
692
- }
693
-
694
- // Extract attributes from the opening tag
695
- let attributeString = spaceIndex > 0
696
- ? openTag.substring(spaceIndex + 1, openTag.length - 1).trim()
697
- : '';
698
-
699
- // For self-closing tags, remove the trailing '/' from attributes
700
- if (isSelfClosing && attributeString.endsWith('/')) {
701
- attributeString = attributeString.substring(0, attributeString.length - 1).trim();
702
- }
703
-
704
- const attributes = this.parseAttributes(attributeString);
705
-
706
- console.log('TagParser DEBUG: parseXMLParameters - found match:', {
707
- paramName: tagName,
708
- attributeString,
709
- valueLength: tagContent.length,
710
- valuePreview: tagContent.substring(0, 50) + (tagContent.length > 50 ? '...' : '')
711
- });
712
-
713
- // CRITICAL FIX: Handle multiple tags with same name (e.g., multiple <write> tags)
714
- // Convert to array if duplicate detected
715
- const paramValue = {
716
- value: tagContent.trim(),
717
- attributes
718
- };
719
-
720
- if (parameters[tagName]) {
721
- // Tag already exists - convert to array or append to existing array
722
- if (Array.isArray(parameters[tagName])) {
723
- // Already an array, append
724
- parameters[tagName].push(paramValue);
725
- console.log('TagParser DEBUG: appended to existing array for tag:', tagName, 'count:', parameters[tagName].length);
726
- } else {
727
- // First duplicate - convert to array
728
- const existingValue = parameters[tagName];
729
- parameters[tagName] = [existingValue, paramValue];
730
- console.log('TagParser DEBUG: converted to array for duplicate tag:', tagName);
731
- }
732
- } else {
733
- // First occurrence - store as single object
734
- parameters[tagName] = paramValue;
735
- }
736
-
737
- // For convenience, also store direct access to value (deprecated, kept for backward compatibility)
738
- // Only define if it doesn't exist (handles multiple tags with same name)
739
- const valuePropertyName = tagName + '_value';
740
- if (!Object.prototype.hasOwnProperty.call(parameters, valuePropertyName)) {
741
- Object.defineProperty(parameters, valuePropertyName, {
742
- value: tagContent.trim(),
743
- enumerable: false
744
- });
745
- }
746
-
747
- foundCount++;
748
-
749
- // Update position based on whether it's self-closing or paired tags
750
- if (isSelfClosing) {
751
- position = openTagEnd + 1;
752
- } else {
753
- const closingTag = `</${tagName}>`;
754
- position = closingTagStart + closingTag.length;
755
- }
756
- }
757
-
758
- console.log('TagParser DEBUG: parseXMLParameters - matches found:', foundCount);
759
- console.log('TagParser DEBUG: parseXMLParameters - final parameters:', Object.keys(parameters));
760
- return parameters;
761
- }
762
-
763
- /**
764
- * Parse attributes from attribute string
765
- * @param {string} attributeString - Attribute string to parse
766
- * @returns {Object} Parsed attributes
767
- */
768
- parseAttributes(attributeString) {
769
- const attributes = {};
770
-
771
- if (!attributeString) return attributes;
772
-
773
- const attrMatches = this.matchAll(attributeString, this.patterns.attribute);
774
-
775
- for (const match of attrMatches) {
776
- const attrName = match.groups[0];
777
- const attrValue = match.groups[1];
778
-
779
- attributes[attrName] = attrValue;
780
- }
781
-
782
- return attributes;
783
- }
784
-
785
- /**
786
- * Extract content from tags
787
- * @param {string} content - Content to search
788
- * @param {string} tagName - Tag name to extract
789
- * @returns {Array} Array of extracted content strings
790
- */
791
- static extractContent(content, tagName) {
792
- const pattern = new RegExp(`<${tagName}[^>]*>([^<]*)<\\/${tagName}>`, 'g');
793
- const matches = [];
794
- let match;
795
-
796
- while ((match = pattern.exec(content)) !== null) {
797
- matches.push(match[1].trim());
798
- }
799
-
800
- return matches;
801
- }
802
-
803
- /**
804
- * Extract tag with attributes
805
- * @param {string} content - Content to search
806
- * @param {string} tagName - Tag name to extract
807
- * @returns {Array} Array of extracted tag objects with content and attributes
808
- */
809
- static extractTagsWithAttributes(content, tagName) {
810
- const pattern = new RegExp(`<${tagName}\\s*([^>]*)>([^<]*)<\\/${tagName}>`, 'g');
811
- const tags = [];
812
- let match;
813
-
814
- while ((match = pattern.exec(content)) !== null) {
815
- const attributeString = match[1];
816
- const tagContent = match[2].trim();
817
-
818
- const parser = new TagParser();
819
- const attributes = parser.parseAttributes(attributeString);
820
-
821
- tags.push({
822
- content: tagContent,
823
- attributes,
824
- rawMatch: match[0]
825
- });
826
- }
827
-
828
- return tags;
829
- }
830
-
831
- /**
832
- * Check if JSON object represents a tool command
833
- * @private
834
- */
835
- isToolCommandJSON(obj) {
836
- return obj &&
837
- typeof obj === 'object' &&
838
- (obj.toolId || obj.tool) &&
839
- (obj.parameters || obj.actions);
840
- }
841
-
842
- /**
843
- * Match all occurrences of a pattern
844
- * @private
845
- */
846
- matchAll(content, pattern) {
847
- const matches = [];
848
- let match;
849
-
850
- // Reset pattern lastIndex to ensure clean matching
851
- pattern.lastIndex = 0;
852
-
853
- while ((match = pattern.exec(content)) !== null) {
854
- matches.push({
855
- match: match[0],
856
- groups: match.slice(1),
857
- index: match.index
858
- });
859
- }
860
-
861
- return matches;
862
- }
863
-
864
- /**
865
- * Validate tool command structure
866
- * @param {Object} command - Tool command to validate
867
- * @returns {Object} Validation result
868
- */
869
- validateToolCommand(command) {
870
- const errors = [];
871
-
872
- if (!command.toolId) {
873
- errors.push('Missing toolId');
874
- }
875
-
876
- if (!command.parameters && !command.actions) {
877
- errors.push('Missing parameters or actions');
878
- }
879
-
880
- if (command.type === 'xml') {
881
- if (!command.rawContent) {
882
- errors.push('Missing rawContent for XML command');
883
- }
884
-
885
- // Validate XML parameter structure
886
- if (command.parameters) {
887
- for (const [paramName, paramData] of Object.entries(command.parameters)) {
888
- if (typeof paramData !== 'object' || !('value' in paramData)) {
889
- errors.push(`Invalid parameter structure for ${paramName}`);
890
- }
891
- }
892
- }
893
- }
894
-
895
- if (command.type === 'json') {
896
- if (!command.jsonData) {
897
- errors.push('Missing jsonData for JSON command');
898
- }
899
- }
900
-
901
- return {
902
- valid: errors.length === 0,
903
- errors
904
- };
905
- }
906
-
907
- /**
908
- * Normalize tool command to consistent format
909
- * @param {Object} command - Tool command to normalize
910
- * @returns {Object} Normalized command
911
- */
912
- normalizeToolCommand(command) {
913
- const normalized = {
914
- toolId: command.toolId,
915
- type: command.type,
916
- parameters: {},
917
- rawContent: command.rawContent
918
- };
919
-
920
- if (command.type === COMMAND_FORMATS.XML) {
921
- console.log('TagParser DEBUG: normalizing XML command with parameters:', Object.keys(command.parameters || {}));
922
-
923
- // SPECIAL CASE: AgentDelay tool expects flat object {duration, reason}, not actions array
924
- if (command.toolId === 'agentdelay') {
925
- const params = command.parameters || {};
926
-
927
- // Extract duration and reason
928
- if (params['pause-duration']) {
929
- const durationStr = params['pause-duration'].value;
930
- normalized.parameters.duration = parseInt(durationStr, 10);
931
- }
932
- if (params['reason']) {
933
- normalized.parameters.reason = params['reason'].value.trim();
934
- }
935
-
936
- console.log('TagParser DEBUG: delay tool - flat parameters:', normalized.parameters);
937
- return normalized;
938
- }
939
-
940
- // SPECIAL CASE: ImageGen tool has its own XML parser, pass raw content directly
941
- if (command.toolId === 'image-gen') {
942
- const params = command.parameters || {};
943
-
944
- // Extract the inner XML content (without the <image-gen> wrapper)
945
- // ImageTool.parseParameters() expects just the inner tags
946
- let xmlContent = '';
947
- for (const [key, paramData] of Object.entries(params)) {
948
- xmlContent += `<${key}>${paramData.value}</${key}>\n`;
949
- }
950
-
951
- // Store the raw XML for ImageTool to parse
952
- normalized.parameters = xmlContent.trim();
953
-
954
- console.log('TagParser DEBUG: image-gen tool - passing raw XML to ImageTool:', xmlContent.substring(0, 100) + '...');
955
- return normalized;
956
- }
957
-
958
- // NORMAL CASE: Convert XML parameters to actions array format for most tools
959
- const actions = [];
960
-
961
- for (const [key, paramData] of Object.entries(command.parameters || {})) {
962
- console.log('TagParser DEBUG: processing XML parameter:', key, 'with data:', paramData);
963
-
964
- // CRITICAL FIX: Handle both single object and array of objects (for duplicate tags)
965
- const paramDataArray = Array.isArray(paramData) ? paramData : [paramData];
966
-
967
- for (const singleParamData of paramDataArray) {
968
- // Convert XML tags to action objects
969
- const action = {
970
- type: key, // e.g., "write", "read", "delete", "run-command"
971
- ...singleParamData.attributes // e.g., output-path, file-path, etc.
972
- };
973
-
974
- // Add content if it exists
975
- if (singleParamData.value && singleParamData.value.trim()) {
976
- action.content = singleParamData.value.trim();
977
- }
978
-
979
- console.log('TagParser DEBUG: created action before normalization:', action);
980
-
981
- // Convert attribute names to camelCase for consistency
982
- const normalizedAction = {};
983
- for (const [attrKey, attrValue] of Object.entries(action)) {
984
- const normalizedKey = this._toCamelCase(attrKey);
985
- normalizedAction[normalizedKey] = attrValue;
986
- }
987
-
988
- // CRITICAL FIX: Map 'content' field to tool-specific field names based on action type
989
- if (normalizedAction.content !== undefined) {
990
- const contentFieldMapping = {
991
- // Terminal tool mappings
992
- 'run-command': 'command',
993
- 'create-directory': 'directory',
994
- 'change-directory': 'directory',
995
- 'list-directory': 'directory',
996
- 'get-working-directory': null, // No content field needed
997
-
998
- // FileSystem tool mappings
999
- 'write': null, // Uses content for file content (keep as-is)
1000
- 'read': 'filePath',
1001
- 'delete': 'filePath',
1002
- 'copy': null, // Uses attributes (source, destination)
1003
- 'move': null, // Uses attributes (source, destination)
1004
- 'append': 'filePath',
1005
- 'create-dir': 'directory',
1006
- 'list': 'directory',
1007
- 'exists': 'path',
1008
- 'stats': 'path',
1009
-
1010
- // TaskManager tool mappings
1011
- 'action': null, // Keep as content
1012
- 'title': null,
1013
- 'description': null,
1014
- 'priority': null,
1015
- 'taskId': null,
1016
- 'status': null
1017
- };
1018
-
1019
- const mappedFieldName = contentFieldMapping[normalizedAction.type];
1020
-
1021
- if (mappedFieldName) {
1022
- // Map content to the specific field name
1023
- normalizedAction[mappedFieldName] = normalizedAction.content;
1024
- delete normalizedAction.content;
1025
- console.log(`TagParser DEBUG: mapped 'content' to '${mappedFieldName}' for action type '${normalizedAction.type}'`);
1026
- } else if (mappedFieldName === null) {
1027
- // Explicitly keep as content or remove if not needed
1028
- console.log(`TagParser DEBUG: keeping action type '${normalizedAction.type}' as-is`);
1029
- }
1030
- }
1031
-
1032
- console.log('TagParser DEBUG: final normalized action:', normalizedAction);
1033
- actions.push(normalizedAction);
1034
- } // End inner loop for paramDataArray
1035
-
1036
- // Preserve original format for backward compatibility (use first value if array)
1037
- const backwardCompatValue = Array.isArray(paramData) ? paramData[0] : paramData;
1038
- normalized.parameters[key] = backwardCompatValue.value;
1039
- if (backwardCompatValue.attributes && Object.keys(backwardCompatValue.attributes).length > 0) {
1040
- normalized.parameters[`${key}_attributes`] = backwardCompatValue.attributes;
1041
- }
1042
- } // End outer loop for parameters
1043
-
1044
- console.log('TagParser DEBUG: total actions created:', actions.length);
1045
-
1046
- // Add actions array if we found any XML actions
1047
- if (actions.length > 0) {
1048
- normalized.parameters.actions = actions;
1049
- console.log('TagParser DEBUG: added actions array to parameters');
1050
- } else {
1051
- console.log('TagParser DEBUG: WARNING - no actions created, this will cause "actions is not iterable" error');
1052
- }
1053
- } else if (command.type === COMMAND_FORMATS.JSON || command.type === COMMAND_FORMATS.JSON_PLAIN) {
1054
- // JSON parameters are already in simple format
1055
- normalized.parameters = { ...command.parameters };
1056
-
1057
- // Handle actions array format (common in agentcommunication tool)
1058
- if (command.actions && Array.isArray(command.actions)) {
1059
- normalized.parameters.actions = command.actions;
1060
-
1061
- // For agentcommunication tool, extract the action from the first item
1062
- if (command.toolId === TOOL_IDS.AGENT_COMMUNICATION && command.actions.length > 0) {
1063
- const firstAction = command.actions[0];
1064
- normalized.parameters.action = firstAction.type || firstAction.action;
1065
- // Spread the rest of the action properties
1066
- Object.assign(normalized.parameters, firstAction);
1067
- }
1068
- }
1069
- }
1070
-
1071
- return normalized;
1072
- }
1073
-
1074
- /**
1075
- * Check if a string is a valid XML tag name for tool commands
1076
- * @param {string} tagName - Tag name to validate
1077
- * @returns {boolean} True if valid
1078
- * @private
1079
- */
1080
- isValidXmlTagName(tagName) {
1081
- // Valid tool command tag names: write, read, delete, copy, move, etc.
1082
- const validTagNames = [
1083
- 'write', 'read', 'delete', 'copy', 'move', 'append',
1084
- 'create-dir', 'list', 'exists', 'stats',
1085
- 'run-command', 'cd', 'pwd',
1086
- // Terminal tool tags
1087
- 'create-directory', 'change-directory', 'list-directory', 'get-working-directory',
1088
- // Agent delay tool tags
1089
- 'pause-duration', 'reason',
1090
- // TaskManager tool tags
1091
- 'action', 'title', 'description', 'priority', 'taskId', 'status',
1092
- 'dependsOn', 'dependencyType', 'relatedTo', 'parentTaskId',
1093
- 'timeframe', 'templateId', 'stage', 'milestone', 'notes',
1094
- // Browser tool tags
1095
- 'url', 'selector', 'text', 'screenshot', 'element',
1096
- // Agent communication tags
1097
- 'recipient', 'message', 'conversation-id',
1098
- // Image generation tool tags
1099
- 'prompt', 'output-path', 'size', 'quality', 'model', 'batch', 'image',
1100
- // General parameter tags
1101
- 'command', 'path', 'content', 'name', 'value', 'type', 'target'
1102
- ];
1103
-
1104
- // Must be a known tag name and contain only letters, numbers, and hyphens
1105
- return validTagNames.includes(tagName) && this.containsOnlyValidChars(tagName);
1106
- }
1107
-
1108
- /**
1109
- * Check if tag name contains only valid characters (letters, numbers, hyphens)
1110
- * @param {string} tagName - Tag name to check
1111
- * @returns {boolean} True if valid
1112
- * @private
1113
- */
1114
- containsOnlyValidChars(tagName) {
1115
- if (!tagName || tagName.length === 0) return false;
1116
-
1117
- // First character must be a letter
1118
- const firstChar = tagName.charAt(0);
1119
- const firstIsLetter = (firstChar >= 'a' && firstChar <= 'z') || (firstChar >= 'A' && firstChar <= 'Z');
1120
- if (!firstIsLetter) {
1121
- return false;
1122
- }
1123
-
1124
- // Rest can be letters, numbers, or hyphens
1125
- for (let i = 1; i < tagName.length; i++) {
1126
- const char = tagName.charAt(i);
1127
- const isLetter = (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z');
1128
- const isNumber = char >= '0' && char <= '9';
1129
- const isHyphen = char === '-';
1130
-
1131
- if (!isLetter && !isNumber && !isHyphen) {
1132
- return false;
1133
- }
1134
- }
1135
-
1136
- return true;
1137
- }
1138
-
1139
- /**
1140
- * Check if tag name is in the valid tag list (for debugging)
1141
- * @param {string} tagName - Tag name to check
1142
- * @returns {boolean} True if in list
1143
- * @private
1144
- */
1145
- isTagInValidList(tagName) {
1146
- const validTagNames = [
1147
- 'write', 'read', 'delete', 'copy', 'move', 'append',
1148
- 'create-dir', 'list', 'exists', 'stats',
1149
- 'run-command', 'cd', 'pwd',
1150
- // Terminal tool tags
1151
- 'create-directory', 'change-directory', 'list-directory', 'get-working-directory',
1152
- // Agent delay tool tags
1153
- 'pause-duration', 'reason',
1154
- // TaskManager tool tags
1155
- 'action', 'title', 'description', 'priority', 'taskId', 'status',
1156
- 'dependsOn', 'dependencyType', 'relatedTo', 'parentTaskId',
1157
- 'timeframe', 'templateId', 'stage', 'milestone', 'notes',
1158
- // Browser tool tags
1159
- 'url', 'selector', 'text', 'screenshot', 'element',
1160
- // Agent communication tags
1161
- 'recipient', 'message', 'conversation-id',
1162
- // Image generation tool tags
1163
- 'prompt', 'output-path', 'size', 'quality', 'model', 'batch', 'image',
1164
- // General parameter tags
1165
- 'command', 'path', 'content', 'name', 'value', 'type', 'target'
1166
- ];
1167
- return validTagNames.includes(tagName);
1168
- }
1169
-
1170
- /**
1171
- * Convert kebab-case or snake_case to camelCase
1172
- * @private
1173
- */
1174
- _toCamelCase(str) {
1175
- return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase());
1176
- }
1177
-
1178
- /**
1179
- * Extract all content between tags, including nested tags
1180
- * @param {string} content - Content to search
1181
- * @param {string} startTag - Opening tag
1182
- * @param {string} endTag - Closing tag
1183
- * @returns {Array} Array of extracted content blocks
1184
- */
1185
- static extractBetweenTags(content, startTag, endTag) {
1186
- const blocks = [];
1187
- let startIndex = 0;
1188
-
1189
- while (true) {
1190
- const start = content.indexOf(startTag, startIndex);
1191
- if (start === -1) break;
1192
-
1193
- const end = content.indexOf(endTag, start + startTag.length);
1194
- if (end === -1) break;
1195
-
1196
- const blockContent = content.substring(start + startTag.length, end);
1197
- blocks.push({
1198
- content: blockContent,
1199
- fullMatch: content.substring(start, end + endTag.length),
1200
- startIndex: start,
1201
- endIndex: end + endTag.length
1202
- });
1203
-
1204
- startIndex = end + endTag.length;
1205
- }
1206
-
1207
- return blocks;
1208
- }
1209
-
1210
- /**
1211
- * Clean content by removing all tool commands and agent redirects
1212
- * @param {string} content - Content to clean
1213
- * @returns {string} Cleaned content
1214
- */
1215
- cleanContent(content) {
1216
- let cleaned = content;
1217
-
1218
- // Remove tool command blocks
1219
- cleaned = cleaned.replace(this.patterns.toolCommand, '');
1220
-
1221
- // Remove agent redirects
1222
- cleaned = cleaned.replace(this.patterns.agentRedirect, '');
1223
-
1224
- // Remove JSON tool command blocks
1225
- cleaned = cleaned.replace(this.patterns.jsonBlock, (match, jsonContent) => {
1226
- try {
1227
- const jsonData = JSON.parse(jsonContent);
1228
- if (this.isToolCommandJSON(jsonData) ||
1229
- (jsonData.toolCommands && Array.isArray(jsonData.toolCommands))) {
1230
- return '';
1231
- }
1232
- } catch {
1233
- // Not a tool command JSON block, keep it
1234
- }
1235
- return match;
1236
- });
1237
-
1238
- // Clean up excessive whitespace
1239
- cleaned = cleaned.replace(/\n\s*\n\s*\n/g, '\n\n');
1240
- cleaned = cleaned.trim();
1241
-
1242
- return cleaned;
1243
- }
1244
- }
1245
-
1246
- export default TagParser;
1
+ function a0_0xebd7(_0x354ce8,_0xb4a95e){_0x354ce8=_0x354ce8-0xb2;const _0x1def0a=a0_0x1def();let _0xebd75e=_0x1def0a[_0x354ce8];if(a0_0xebd7['EerrwF']===undefined){var _0x59ce61=function(_0x3594e2){const _0x4263f7='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x3be2f9='',_0x56a718='';for(let _0x1137cd=0x0,_0x217b20,_0xa53053,_0x5d0331=0x0;_0xa53053=_0x3594e2['charAt'](_0x5d0331++);~_0xa53053&&(_0x217b20=_0x1137cd%0x4?_0x217b20*0x40+_0xa53053:_0xa53053,_0x1137cd++%0x4)?_0x3be2f9+=String['fromCharCode'](0xff&_0x217b20>>(-0x2*_0x1137cd&0x6)):0x0){_0xa53053=_0x4263f7['indexOf'](_0xa53053);}for(let _0x5eb260=0x0,_0x8b08be=_0x3be2f9['length'];_0x5eb260<_0x8b08be;_0x5eb260++){_0x56a718+='%'+('00'+_0x3be2f9['charCodeAt'](_0x5eb260)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x56a718);};a0_0xebd7['RopbBu']=_0x59ce61,a0_0xebd7['QxGaXM']={},a0_0xebd7['EerrwF']=!![];}const _0x4e89ac=_0x1def0a[0x0],_0x5676f2=_0x354ce8+_0x4e89ac,_0x245caa=a0_0xebd7['QxGaXM'][_0x5676f2];return!_0x245caa?(_0xebd75e=a0_0xebd7['RopbBu'](_0xebd75e),a0_0xebd7['QxGaXM'][_0x5676f2]=_0xebd75e):_0xebd75e=_0x245caa,_0xebd75e;}const a0_0x3c3855=a0_0xebd7;(function(_0x464eee,_0x318735){const _0x562c60=a0_0xebd7,_0x105b00=_0x464eee();while(!![]){try{const _0x18f355=parseInt(_0x562c60(0x13f))/0x1+parseInt(_0x562c60(0xe8))/0x2+-parseInt(_0x562c60(0x119))/0x3*(-parseInt(_0x562c60(0xd7))/0x4)+parseInt(_0x562c60(0xf5))/0x5*(parseInt(_0x562c60(0xe5))/0x6)+parseInt(_0x562c60(0xcb))/0x7*(-parseInt(_0x562c60(0x113))/0x8)+-parseInt(_0x562c60(0x10f))/0x9+-parseInt(_0x562c60(0x100))/0xa;if(_0x18f355===_0x318735)break;else _0x105b00['push'](_0x105b00['shift']());}catch(_0x1ccd04){_0x105b00['push'](_0x105b00['shift']());}}}(a0_0x1def,0x562cd));import{AGENT_REDIRECT_ATTRIBUTES}from'./constants.js';import{TOOL_IDS,COMMAND_FORMATS,JSON_STRUCTURES,identifyJsonStructure,getToolIdFromAction,isValidToolId}from'./toolConstants.js';class TagParser{constructor(){this['patterns']={'toolCommand':/<tool-command>(.*?)<\/tool-command>/gs,'tool':/<tool\s+([^>]*)>(.*?)<\/tool>/gs,'parameter':/<([^>\s]+)(?:\s+([^>]*))?>(((?!<\/\1>)[\s\S])*)<\/\1>/g,'attribute':/([\w-]+)=["']([^"']*)["']/g,'agentRedirect':/\[agent-redirect\s+([^\]]*)\](.*?)\[\/agent-redirect\]/gs,'jsonBlock':/```json\s*(\{[\s\S]*?\})\s*```/g,'plainJson':/^(\{(?:[^{}]|(?:\{[^{}]*\}))*\})$/gm};}['decodeHtmlEntities'](_0x3be2f9){const _0x56a718={'&lt;':'<','&gt;':'>','&amp;':'&','&quot;':'\x22','&#x27;':'\x27','&#x2F;':'/','&#39;':'\x27','&#47;':'/'};return _0x3be2f9['replace'](/&(?:lt|gt|amp|quot|#x27|#x2F|#39|#47);/g,_0x1137cd=>_0x56a718[_0x1137cd]||_0x1137cd);}['extractToolCommands'](_0x217b20){const _0x5d603a=a0_0xebd7,_0xa53053=[],_0x5d0331=this[_0x5d603a(0xdc)](_0x217b20),_0x5eb260=this['extractXMLToolCommands'](_0x5d0331);_0xa53053[_0x5d603a(0xbb)](..._0x5eb260);const _0x8b08be=this['extractJSONCodeBlocks'](_0x5d0331);_0xa53053[_0x5d603a(0xbb)](..._0x8b08be);const _0x37dbec=this[_0x5d603a(0xea)](_0x5d0331),_0x4280e5=this['extractPlainJSON'](_0x37dbec);return _0xa53053['push'](..._0x4280e5),_0xa53053;}['removeToolInvocationBlocks'](_0xc7f029){const _0x2e71c5=a0_0xebd7;let _0x3cdcdc=_0xc7f029,_0x20eaed=0x0;while(_0x20eaed<_0x3cdcdc['length']){const _0xe0219e='```json',_0x512698=_0x2e71c5(0x135),_0x3e54d6=_0x3cdcdc[_0x2e71c5(0xe3)](_0xe0219e,_0x20eaed);if(_0x3e54d6===-0x1)break;const _0x31215f=_0x3e54d6+_0xe0219e[_0x2e71c5(0xf6)],_0x23b233=_0x3cdcdc['indexOf'](_0x512698,_0x31215f);if(_0x23b233===-0x1)break;const _0x18b067=_0x3cdcdc[_0x2e71c5(0x146)](0x0,_0x3e54d6),_0xbfd63d=_0x3cdcdc['substring'](_0x23b233+_0x512698['length']);_0x3cdcdc=_0x18b067+_0x2e71c5(0xf7)+_0xbfd63d,_0x20eaed=_0x3e54d6+_0x2e71c5(0xf7)[_0x2e71c5(0xf6)];}const _0x1c51e2=['taskmanager',_0x2e71c5(0xe0),_0x2e71c5(0x131),_0x2e71c5(0x132),_0x2e71c5(0x134),_0x2e71c5(0x126),'agentdelay',_0x2e71c5(0xfd)];for(const _0x4c536f of _0x1c51e2){const _0x4a2bc9='<'+_0x4c536f+'>',_0x262a20='</'+_0x4c536f+'>';let _0x20d5e5=0x0;while(_0x20d5e5<_0x3cdcdc['length']){const _0x596523=_0x3cdcdc['indexOf'](_0x4a2bc9,_0x20d5e5);if(_0x596523===-0x1)break;const _0x3e3324=_0x3cdcdc[_0x2e71c5(0xe3)](_0x262a20,_0x596523+_0x4a2bc9['length']);if(_0x3e3324===-0x1)break;const _0x48fc0e=_0x3cdcdc['substring'](0x0,_0x596523),_0x2bf74a=_0x3cdcdc['substring'](_0x3e3324+_0x262a20['length']);_0x3cdcdc=_0x48fc0e+(_0x2e71c5(0x13e)+_0x4c536f+']')+_0x2bf74a,_0x20d5e5=_0x596523+(_0x2e71c5(0x13e)+_0x4c536f+']')[_0x2e71c5(0xf6)];}}let _0x9bbe16=0x0;while(_0x9bbe16<_0x3cdcdc['length']){const _0xfea25a='[tool\x20id=\x22',_0x492c56=_0x3cdcdc['indexOf'](_0xfea25a,_0x9bbe16);if(_0x492c56===-0x1)break;const _0x288e6c=_0x492c56+_0xfea25a['length'],_0x5ea3ce=_0x3cdcdc['indexOf']('\x22',_0x288e6c);if(_0x5ea3ce===-0x1)break;const _0x17218e=_0x3cdcdc[_0x2e71c5(0x146)](_0x288e6c,_0x5ea3ce),_0x5357d2=_0x3cdcdc[_0x2e71c5(0xe3)](']',_0x5ea3ce);if(_0x5357d2===-0x1)break;const _0x3ef0f6=_0x2e71c5(0xbe),_0x559d56=_0x3cdcdc['indexOf'](_0x3ef0f6,_0x5357d2);if(_0x559d56===-0x1)break;const _0x1846df=_0x3cdcdc['substring'](0x0,_0x492c56),_0x4f7bc2=_0x3cdcdc[_0x2e71c5(0x146)](_0x559d56+_0x3ef0f6[_0x2e71c5(0xf6)]);_0x3cdcdc=_0x1846df+('[BRACKET_TOOL_REMOVED:'+_0x17218e+']')+_0x4f7bc2,_0x9bbe16=_0x492c56+('[BRACKET_TOOL_REMOVED:'+_0x17218e+']')[_0x2e71c5(0xf6)];}return _0x3cdcdc;}['extractXMLToolCommands'](_0xd219cc){const _0x569823=a0_0xebd7,_0x263891=[],_0x624eeb=this[_0x569823(0xfa)](_0xd219cc,this[_0x569823(0x142)][_0x569823(0xd2)]);for(const _0x2fe493 of _0x624eeb){const _0xd6860a=_0x2fe493[_0x569823(0xeb)][0x1],_0x1ebda2=this['matchAll'](_0xd6860a,this['patterns']['tool']);for(const _0x5338a1 of _0x1ebda2){const _0x12bd80=this['parseAttributes'](_0x5338a1['groups'][0x1]),_0x4b5088=_0x5338a1['groups'][0x2],_0x187d26={'type':COMMAND_FORMATS[_0x569823(0xcc)],'toolId':_0x12bd80['id'],'attributes':_0x12bd80,'parameters':this[_0x569823(0xc2)](_0x4b5088),'rawContent':_0x5338a1[_0x569823(0x121)]['trim'](),'blockContent':_0x2fe493['match'][_0x569823(0x104)]()};_0x263891['push'](_0x187d26);}}const _0x36f4c2=this[_0x569823(0x11c)](_0xd219cc);_0x263891[_0x569823(0xbb)](..._0x36f4c2);const _0x4273a3=this[_0x569823(0x11e)](_0xd219cc);return _0x263891[_0x569823(0xbb)](..._0x4273a3),_0x263891;}['extractDirectToolTags'](_0x21ac5c){const _0x46a812=a0_0xebd7,_0x3b689c=[],_0x18296b=['taskmanager',_0x46a812(0xe0),_0x46a812(0x131),_0x46a812(0x132),_0x46a812(0x134),_0x46a812(0x126),'agentdelay','image-gen'];for(const _0x24e4c6 of _0x18296b){const _0x292805=this['extractToolByName'](_0x21ac5c,_0x24e4c6);_0x3b689c['push'](..._0x292805);}return _0x3b689c;}[a0_0x3c3855(0x11e)](_0x3045f9){const _0x36628d=a0_0x3c3855,_0x175e2c=[],_0x515dba='[tool\x20id=\x22',_0xbdf834='[/tool]';let _0x4dc257=0x0;while(_0x4dc257<_0x3045f9['length']){const _0xe98208=_0x3045f9['indexOf'](_0x515dba,_0x4dc257);if(_0xe98208===-0x1)break;const _0x2b41ba=_0xe98208+_0x515dba['length'],_0x1d4964=_0x3045f9[_0x36628d(0xe3)]('\x22',_0x2b41ba);if(_0x1d4964===-0x1)break;const _0xb1995e=_0x3045f9['substring'](_0x2b41ba,_0x1d4964),_0x13bb9e=_0x3045f9['indexOf'](']',_0x1d4964);if(_0x13bb9e===-0x1)break;const _0x245c26=_0x3045f9['indexOf'](_0xbdf834,_0x13bb9e);if(_0x245c26===-0x1)break;const _0x1838cf=_0x3045f9['substring'](_0x13bb9e+0x1,_0x245c26),_0x376a93=_0x3045f9[_0x36628d(0x146)](_0xe98208,_0x245c26+_0xbdf834['length']);console['log'](_0x36628d(0xf4)+_0xb1995e+_0x36628d(0xf1));const _0x338eed={'type':COMMAND_FORMATS[_0x36628d(0xcc)],'toolId':_0xb1995e,'attributes':{},'parameters':this['parseXMLParameters'](_0x1838cf),'rawContent':_0x376a93['trim'](),'blockContent':_0x376a93['trim']()};_0x175e2c['push'](_0x338eed),_0x4dc257=_0x245c26+_0xbdf834['length'];}return _0x175e2c;}[a0_0x3c3855(0x108)](_0x5ef341,_0x49638d){const _0x423a02=a0_0x3c3855,_0x326ef3=[],_0x2e2d6b='<'+_0x49638d+'>',_0x1473e1='</'+_0x49638d+'>';let _0x2c51b1=0x0;while(_0x2c51b1<_0x5ef341[_0x423a02(0xf6)]){const _0x3e215b=_0x5ef341[_0x423a02(0xe3)](_0x2e2d6b,_0x2c51b1);if(_0x3e215b===-0x1)break;const _0x5c3641=_0x3e215b+_0x2e2d6b[_0x423a02(0xf6)],_0x410571=_0x5ef341['indexOf'](_0x1473e1,_0x5c3641);if(_0x410571===-0x1){_0x2c51b1=_0x5c3641;continue;}const _0x4afd37=_0x5ef341['substring'](_0x5c3641,_0x410571),_0x82b231=_0x5ef341['substring'](_0x3e215b,_0x410571+_0x1473e1[_0x423a02(0xf6)]);console[_0x423a02(0xd9)]('TagParser\x20DEBUG:\x20extractToolByName\x20-\x20found\x20'+_0x49638d+'\x20tool');const _0x4ab659={'type':COMMAND_FORMATS['XML'],'toolId':_0x49638d,'attributes':{},'parameters':this[_0x423a02(0xc2)](_0x4afd37),'rawContent':_0x82b231[_0x423a02(0x104)](),'blockContent':_0x82b231[_0x423a02(0x104)]()};_0x326ef3[_0x423a02(0xbb)](_0x4ab659),_0x2c51b1=_0x410571+_0x1473e1[_0x423a02(0xf6)];}return _0x326ef3;}['extractJSONToolCommands'](_0x17af4d){const _0x4ce19f=a0_0x3c3855,_0x318bfd=[];return _0x318bfd[_0x4ce19f(0xbb)](...this[_0x4ce19f(0x12b)](_0x17af4d)),_0x318bfd[_0x4ce19f(0xbb)](...this[_0x4ce19f(0x116)](_0x17af4d)),_0x318bfd;}[a0_0x3c3855(0x12b)](_0x278da8){const _0x2670ae=a0_0x3c3855,_0x5b8b99=[];let _0x41bb65=0x0;while(!![]){const _0x402638=_0x2670ae(0xd1),_0x50a707='```',_0x670fb0=_0x278da8[_0x2670ae(0xe3)](_0x402638,_0x41bb65);if(_0x670fb0===-0x1)break;const _0x24e378=_0x670fb0+_0x402638[_0x2670ae(0xf6)],_0x104897=_0x278da8[_0x2670ae(0xe3)](_0x50a707,_0x24e378);if(_0x104897===-0x1)break;const _0x5830c4=_0x278da8[_0x2670ae(0x146)](_0x24e378,_0x104897)[_0x2670ae(0x104)]();try{const _0x3e89ab=JSON[_0x2670ae(0xd3)](_0x5830c4);if(this[_0x2670ae(0xdf)](_0x3e89ab)){const _0x3879fb=_0x3e89ab[_0x2670ae(0xb7)]||_0x3e89ab['tool'];if(!_0x3879fb||_0x3879fb==='unknown'){console['log']('TagParser\x20DEBUG:\x20Skipping\x20JSON\x20block\x20-\x20missing\x20explicit\x20toolId'),_0x41bb65=_0x104897+_0x50a707[_0x2670ae(0xf6)];continue;}const _0x4fa537={'type':COMMAND_FORMATS[_0x2670ae(0xf8)],'toolId':_0x3879fb,'parameters':_0x3e89ab['parameters']||_0x3e89ab['actions']||{},'actions':_0x3e89ab['actions'],'rawContent':_0x278da8[_0x2670ae(0x146)](_0x670fb0,_0x104897+_0x50a707['length']),'jsonData':_0x3e89ab};_0x5b8b99['push'](_0x4fa537);}if(_0x3e89ab['toolCommands']&&Array[_0x2670ae(0x114)](_0x3e89ab[_0x2670ae(0xd4)]))for(const _0x29fad2 of _0x3e89ab['toolCommands']){if(this[_0x2670ae(0xdf)](_0x29fad2)){const _0x27b346=_0x29fad2['toolId']||_0x29fad2['tool'];if(!_0x27b346||_0x27b346===_0x2670ae(0x112)){console[_0x2670ae(0xd9)]('TagParser\x20DEBUG:\x20Skipping\x20toolCommand\x20-\x20missing\x20explicit\x20toolId');continue;}const _0x4db751={'type':COMMAND_FORMATS[_0x2670ae(0xf8)],'toolId':_0x27b346,'parameters':_0x29fad2['parameters']||_0x29fad2['actions']||{},'actions':_0x29fad2['actions'],'rawContent':JSON['stringify'](_0x29fad2,null,0x2),'jsonData':_0x29fad2};_0x5b8b99[_0x2670ae(0xbb)](_0x4db751);}}}catch(_0x3972a7){}_0x41bb65=_0x104897+_0x50a707[_0x2670ae(0xf6)];}return _0x5b8b99;}['extractPlainJSON'](_0x300226){const _0x55d677=a0_0x3c3855,_0x507a4d=[],_0x19bf1b=_0x300226['split']('\x0a');for(let _0x40aa42=0x0;_0x40aa42<_0x19bf1b[_0x55d677(0xf6)];_0x40aa42++){const _0x21b0f4=_0x19bf1b[_0x40aa42]['trim']();if(!_0x21b0f4['startsWith']('{'))continue;let _0x54e702='',_0x521bca=0x0,_0x531845=![];for(let _0x5ab511=_0x40aa42;_0x5ab511<_0x19bf1b['length'];_0x5ab511++){const _0x368bd2=_0x19bf1b[_0x5ab511][_0x55d677(0x104)]();_0x54e702+=(_0x5ab511>_0x40aa42?'\x0a':'')+_0x368bd2;for(const _0x79284a of _0x368bd2){if(_0x79284a==='{')_0x521bca++;if(_0x79284a==='}')_0x521bca--;if(_0x521bca===0x0&&_0x79284a==='}'){_0x531845=!![];break;}}if(_0x531845)break;}if(!_0x531845)continue;try{const _0x309d14=JSON['parse'](_0x54e702);if(this[_0x55d677(0xdf)](_0x309d14)||_0x309d14['actions']&&Array['isArray'](_0x309d14['actions'])||_0x309d14['type']&&typeof _0x309d14['type']==='string'){const _0x4fcb44=_0x309d14['toolId']||_0x309d14[_0x55d677(0xfb)]||this['inferToolFromActions'](_0x309d14);if(!_0x4fcb44||_0x4fcb44==='unknown'){console[_0x55d677(0xd9)](_0x55d677(0x125));continue;}const _0x4326f3={'type':COMMAND_FORMATS[_0x55d677(0x10b)],'toolId':_0x4fcb44,'parameters':_0x309d14[_0x55d677(0xee)]||_0x309d14,'actions':_0x309d14[_0x55d677(0xb9)],'rawContent':_0x54e702,'jsonData':_0x309d14,'warning':_0x55d677(0x13b)};_0x507a4d['push'](_0x4326f3);}}catch(_0x1c5ed2){continue;}}return _0x507a4d;}[a0_0x3c3855(0xff)](_0x3e2d0c){const _0x4b4958=a0_0x3c3855,_0x5844e8=identifyJsonStructure(_0x3e2d0c);switch(_0x5844e8){case JSON_STRUCTURES[_0x4b4958(0xd8)]:return _0x3e2d0c[_0x4b4958(0xb7)]||'unknown';case JSON_STRUCTURES[_0x4b4958(0x136)]:if(_0x3e2d0c[_0x4b4958(0xb9)]&&_0x3e2d0c[_0x4b4958(0xb9)][_0x4b4958(0xf6)]>0x0){const _0x1156b7=_0x3e2d0c[_0x4b4958(0xb9)][0x0],_0xce4831=getToolIdFromAction(_0x1156b7['type']);return _0xce4831||_0x4b4958(0x112);}break;case JSON_STRUCTURES[_0x4b4958(0x10a)]:const _0x1780c8=getToolIdFromAction(_0x3e2d0c[_0x4b4958(0x11a)]);return _0x1780c8||_0x4b4958(0x112);case JSON_STRUCTURES['TOOL_COMMANDS']:if(_0x3e2d0c[_0x4b4958(0xd4)]&&_0x3e2d0c[_0x4b4958(0xd4)]['length']>0x0)return this[_0x4b4958(0xff)](_0x3e2d0c[_0x4b4958(0xd4)][0x0]);break;}return _0x4b4958(0x112);}[a0_0x3c3855(0xc7)](_0x3f32b3){const _0xd637af=a0_0x3c3855,_0x544635=[],_0x163c41=this['matchAll'](_0x3f32b3,this[_0xd637af(0x142)][_0xd637af(0x129)]);for(const _0x2d3708 of _0x163c41){const _0x24e8f9=_0x2d3708[_0xd637af(0xeb)][0x1],_0x1d80bc=_0x2d3708[_0xd637af(0xeb)][0x2]['trim'](),_0x13c900=this['parseAttributes'](_0x24e8f9),_0x231303={'to':_0x13c900['to'],'content':_0x1d80bc,'urgent':_0x13c900[AGENT_REDIRECT_ATTRIBUTES['URGENT']]==='true','requiresResponse':_0x13c900[AGENT_REDIRECT_ATTRIBUTES[_0xd637af(0xd5)]]===_0xd637af(0xb6),'context':_0x13c900[AGENT_REDIRECT_ATTRIBUTES['CONTEXT']],'rawMatch':_0x2d3708[_0xd637af(0x121)]};for(const [_0x2be141,_0x307386]of Object['entries'](_0x13c900)){!['to',AGENT_REDIRECT_ATTRIBUTES[_0xd637af(0xec)],AGENT_REDIRECT_ATTRIBUTES[_0xd637af(0xd5)],AGENT_REDIRECT_ATTRIBUTES['CONTEXT']][_0xd637af(0x133)](_0x2be141)&&(_0x231303[_0x2be141]=_0x307386);}_0x544635[_0xd637af(0xbb)](_0x231303);}return _0x544635;}[a0_0x3c3855(0xc2)](_0x845dba){const _0x3654a7=a0_0x3c3855,_0x1237be={};console[_0x3654a7(0xd9)]('TagParser\x20DEBUG:\x20parseXMLParameters\x20-\x20content\x20length:',_0x845dba['length']);let _0x1e2ea6=0x0,_0x488b3e=0x0;while(_0x1e2ea6<_0x845dba[_0x3654a7(0xf6)]){const _0x45259f=_0x845dba[_0x3654a7(0xe3)]('<',_0x1e2ea6);if(_0x45259f===-0x1)break;const _0x1beb82=_0x845dba[_0x3654a7(0xe3)]('>',_0x45259f);if(_0x1beb82===-0x1)break;const _0x1d6e1c=_0x845dba['substring'](_0x45259f,_0x1beb82+0x1),_0x55f4cf=_0x1d6e1c[_0x3654a7(0xe3)]('\x20'),_0x329f84=_0x55f4cf>0x0?_0x1d6e1c[_0x3654a7(0x146)](0x1,_0x55f4cf):_0x1d6e1c['substring'](0x1,_0x1d6e1c['length']-0x1),_0x23de08=this['isValidXmlTagName'](_0x329f84);if(_0x329f84[_0x3654a7(0x133)]('/')||!_0x329f84||!this[_0x3654a7(0xda)](_0x329f84)){_0x1e2ea6=_0x1beb82+0x1;continue;}const _0x195b1c=_0x1d6e1c[_0x3654a7(0xf2)]('/>');let _0x12c4c8='',_0x5de130=_0x1beb82;if(_0x195b1c)_0x12c4c8='',_0x5de130=_0x1beb82;else{const _0x5b2633='</'+_0x329f84+'>';_0x5de130=_0x845dba['indexOf'](_0x5b2633,_0x1beb82+0x1);if(_0x5de130===-0x1){_0x1e2ea6=_0x1beb82+0x1;continue;}_0x12c4c8=_0x845dba[_0x3654a7(0x146)](_0x1beb82+0x1,_0x5de130);}let _0x41ad99=_0x55f4cf>0x0?_0x1d6e1c[_0x3654a7(0x146)](_0x55f4cf+0x1,_0x1d6e1c['length']-0x1)[_0x3654a7(0x104)]():'';_0x195b1c&&_0x41ad99['endsWith']('/')&&(_0x41ad99=_0x41ad99['substring'](0x0,_0x41ad99[_0x3654a7(0xf6)]-0x1)[_0x3654a7(0x104)]());const _0x54fd52=this[_0x3654a7(0xed)](_0x41ad99);console[_0x3654a7(0xd9)]('TagParser\x20DEBUG:\x20parseXMLParameters\x20-\x20found\x20match:',{'paramName':_0x329f84,'attributeString':_0x41ad99,'valueLength':_0x12c4c8['length'],'valuePreview':_0x12c4c8[_0x3654a7(0x146)](0x0,0x32)+(_0x12c4c8[_0x3654a7(0xf6)]>0x32?'...':'')});const _0x1ca9ec={'value':_0x12c4c8[_0x3654a7(0x104)](),'attributes':_0x54fd52};if(_0x1237be[_0x329f84]){if(Array[_0x3654a7(0x114)](_0x1237be[_0x329f84]))_0x1237be[_0x329f84]['push'](_0x1ca9ec),console['log']('TagParser\x20DEBUG:\x20appended\x20to\x20existing\x20array\x20for\x20tag:',_0x329f84,_0x3654a7(0x12a),_0x1237be[_0x329f84][_0x3654a7(0xf6)]);else{const _0x437c6b=_0x1237be[_0x329f84];_0x1237be[_0x329f84]=[_0x437c6b,_0x1ca9ec],console[_0x3654a7(0xd9)]('TagParser\x20DEBUG:\x20converted\x20to\x20array\x20for\x20duplicate\x20tag:',_0x329f84);}}else _0x1237be[_0x329f84]=_0x1ca9ec;const _0x2b575f=_0x329f84+_0x3654a7(0x122);!Object['prototype'][_0x3654a7(0xe9)][_0x3654a7(0x107)](_0x1237be,_0x2b575f)&&Object['defineProperty'](_0x1237be,_0x2b575f,{'value':_0x12c4c8['trim'](),'enumerable':![]});_0x488b3e++;if(_0x195b1c)_0x1e2ea6=_0x1beb82+0x1;else{const _0x3e4cfa='</'+_0x329f84+'>';_0x1e2ea6=_0x5de130+_0x3e4cfa[_0x3654a7(0xf6)];}}return console[_0x3654a7(0xd9)]('TagParser\x20DEBUG:\x20parseXMLParameters\x20-\x20matches\x20found:',_0x488b3e),console[_0x3654a7(0xd9)]('TagParser\x20DEBUG:\x20parseXMLParameters\x20-\x20final\x20parameters:',Object['keys'](_0x1237be)),_0x1237be;}['parseAttributes'](_0x2c729b){const _0x48cc34=a0_0x3c3855,_0x22af3b={};if(!_0x2c729b)return _0x22af3b;const _0x10443c=this[_0x48cc34(0xfa)](_0x2c729b,this[_0x48cc34(0x142)]['attribute']);for(const _0x5f6a40 of _0x10443c){const _0x540a18=_0x5f6a40[_0x48cc34(0xeb)][0x0],_0x2b4720=_0x5f6a40[_0x48cc34(0xeb)][0x1];_0x22af3b[_0x540a18]=_0x2b4720;}return _0x22af3b;}static[a0_0x3c3855(0x138)](_0x105110,_0x563fe3){const _0x1b3102=a0_0x3c3855,_0x47033f=new RegExp('<'+_0x563fe3+'[^>]*>([^<]*)<\x5c/'+_0x563fe3+'>','g'),_0x3b425c=[];let _0x515e95;while((_0x515e95=_0x47033f[_0x1b3102(0x117)](_0x105110))!==null){_0x3b425c['push'](_0x515e95[0x1]['trim']());}return _0x3b425c;}static[a0_0x3c3855(0x143)](_0x5a9195,_0x321f55){const _0x59ee37=a0_0x3c3855,_0x2d5c63=new RegExp('<'+_0x321f55+'\x5cs*([^>]*)>([^<]*)<\x5c/'+_0x321f55+'>','g'),_0x5c8de8=[];let _0x58ddf3;while((_0x58ddf3=_0x2d5c63['exec'](_0x5a9195))!==null){const _0x3fd0a3=_0x58ddf3[0x1],_0x1736f8=_0x58ddf3[0x2]['trim'](),_0x589947=new TagParser(),_0x4e3095=_0x589947[_0x59ee37(0xed)](_0x3fd0a3);_0x5c8de8['push']({'content':_0x1736f8,'attributes':_0x4e3095,'rawMatch':_0x58ddf3[0x0]});}return _0x5c8de8;}[a0_0x3c3855(0xdf)](_0x3b77ea){const _0x1682ee=a0_0x3c3855;return _0x3b77ea&&typeof _0x3b77ea===_0x1682ee(0xe6)&&(_0x3b77ea['toolId']||_0x3b77ea[_0x1682ee(0xfb)])&&(_0x3b77ea['parameters']||_0x3b77ea[_0x1682ee(0xb9)]);}[a0_0x3c3855(0xfa)](_0x35027b,_0x50530c){const _0x46753b=a0_0x3c3855,_0x34e346=[];let _0x1f1c7d;_0x50530c[_0x46753b(0xbd)]=0x0;while((_0x1f1c7d=_0x50530c[_0x46753b(0x117)](_0x35027b))!==null){_0x34e346['push']({'match':_0x1f1c7d[0x0],'groups':_0x1f1c7d['slice'](0x1),'index':_0x1f1c7d['index']});}return _0x34e346;}[a0_0x3c3855(0xdd)](_0xa49a05){const _0xc416e1=a0_0x3c3855,_0x1f745b=[];!_0xa49a05['toolId']&&_0x1f745b[_0xc416e1(0xbb)]('Missing\x20toolId');!_0xa49a05[_0xc416e1(0xee)]&&!_0xa49a05[_0xc416e1(0xb9)]&&_0x1f745b['push'](_0xc416e1(0x144));if(_0xa49a05[_0xc416e1(0x11a)]==='xml'){!_0xa49a05['rawContent']&&_0x1f745b['push']('Missing\x20rawContent\x20for\x20XML\x20command');if(_0xa49a05['parameters'])for(const [_0xcd2e0a,_0x5b37f7]of Object[_0xc416e1(0x127)](_0xa49a05['parameters'])){(typeof _0x5b37f7!==_0xc416e1(0xe6)||!(_0xc416e1(0xcf)in _0x5b37f7))&&_0x1f745b[_0xc416e1(0xbb)]('Invalid\x20parameter\x20structure\x20for\x20'+_0xcd2e0a);}}return _0xa49a05[_0xc416e1(0x11a)]==='json'&&(!_0xa49a05[_0xc416e1(0xdb)]&&_0x1f745b['push'](_0xc416e1(0xc1))),{'valid':_0x1f745b[_0xc416e1(0xf6)]===0x0,'errors':_0x1f745b};}['normalizeToolCommand'](_0x486a7f){const _0x466a3f=a0_0x3c3855,_0x1277b6={'toolId':_0x486a7f[_0x466a3f(0xb7)],'type':_0x486a7f['type'],'parameters':{},'rawContent':_0x486a7f['rawContent']};if(_0x486a7f['type']===COMMAND_FORMATS['XML']){console['log'](_0x466a3f(0xef),Object[_0x466a3f(0x13c)](_0x486a7f['parameters']||{}));if(_0x486a7f['toolId']===_0x466a3f(0xd0)){const _0x51e3dc=_0x486a7f['parameters']||{};if(_0x51e3dc[_0x466a3f(0x11d)]){const _0x4786e1=_0x51e3dc['pause-duration'][_0x466a3f(0xcf)];_0x1277b6[_0x466a3f(0xee)]['duration']=parseInt(_0x4786e1,0xa);}return _0x51e3dc['reason']&&(_0x1277b6['parameters']['reason']=_0x51e3dc['reason'][_0x466a3f(0xcf)][_0x466a3f(0x104)]()),console['log']('TagParser\x20DEBUG:\x20delay\x20tool\x20-\x20flat\x20parameters:',_0x1277b6['parameters']),_0x1277b6;}if(_0x486a7f[_0x466a3f(0xb7)]==='image-gen'){const _0x2b40c6=_0x486a7f['parameters']||{};let _0x41ec58='';for(const [_0x24a757,_0x1ef5f3]of Object[_0x466a3f(0x127)](_0x2b40c6)){_0x41ec58+='<'+_0x24a757+'>'+_0x1ef5f3['value']+'</'+_0x24a757+'>\x0a';}return _0x1277b6['parameters']=_0x41ec58[_0x466a3f(0x104)](),console['log']('TagParser\x20DEBUG:\x20image-gen\x20tool\x20-\x20passing\x20raw\x20XML\x20to\x20ImageTool:',_0x41ec58[_0x466a3f(0x146)](0x0,0x64)+'...'),_0x1277b6;}const _0x59379=[];for(const [_0x49b40a,_0x46ca72]of Object[_0x466a3f(0x127)](_0x486a7f[_0x466a3f(0xee)]||{})){console[_0x466a3f(0xd9)](_0x466a3f(0x13d),_0x49b40a,_0x466a3f(0x103),_0x46ca72);const _0x864a8d=Array['isArray'](_0x46ca72)?_0x46ca72:[_0x46ca72];for(const _0x4069ae of _0x864a8d){const _0x51ada={'type':_0x49b40a,..._0x4069ae[_0x466a3f(0x145)]};_0x4069ae[_0x466a3f(0xcf)]&&_0x4069ae['value'][_0x466a3f(0x104)]()&&(_0x51ada[_0x466a3f(0x140)]=_0x4069ae[_0x466a3f(0xcf)][_0x466a3f(0x104)]());console[_0x466a3f(0xd9)]('TagParser\x20DEBUG:\x20created\x20action\x20before\x20normalization:',_0x51ada);const _0xb6033f={};for(const [_0x52a707,_0x28906f]of Object[_0x466a3f(0x127)](_0x51ada)){const _0x1791ec=this[_0x466a3f(0xce)](_0x52a707);_0xb6033f[_0x1791ec]=_0x28906f;}if(_0xb6033f['content']!==undefined){const _0x1c0bf4={'run-command':'command','create-directory':'directory','change-directory':'directory','list-directory':'directory','get-working-directory':null,'write':null,'read':_0x466a3f(0x111),'delete':'filePath','copy':null,'move':null,'append':'filePath','create-dir':'directory','list':'directory','exists':_0x466a3f(0xfe),'stats':'path','action':null,'title':null,'description':null,'priority':null,'taskId':null,'status':null},_0x155e84=_0x1c0bf4[_0xb6033f[_0x466a3f(0x11a)]];if(_0x155e84)_0xb6033f[_0x155e84]=_0xb6033f[_0x466a3f(0x140)],delete _0xb6033f['content'],console[_0x466a3f(0xd9)](_0x466a3f(0xb2)+_0x155e84+'\x27\x20for\x20action\x20type\x20\x27'+_0xb6033f[_0x466a3f(0x11a)]+'\x27');else _0x155e84===null&&console[_0x466a3f(0xd9)](_0x466a3f(0x106)+_0xb6033f[_0x466a3f(0x11a)]+'\x27\x20as-is');}console[_0x466a3f(0xd9)]('TagParser\x20DEBUG:\x20final\x20normalized\x20action:',_0xb6033f),_0x59379[_0x466a3f(0xbb)](_0xb6033f);}const _0x4673ab=Array[_0x466a3f(0x114)](_0x46ca72)?_0x46ca72[0x0]:_0x46ca72;_0x1277b6[_0x466a3f(0xee)][_0x49b40a]=_0x4673ab[_0x466a3f(0xcf)],_0x4673ab['attributes']&&Object['keys'](_0x4673ab[_0x466a3f(0x145)])['length']>0x0&&(_0x1277b6['parameters'][_0x49b40a+'_attributes']=_0x4673ab[_0x466a3f(0x145)]);}console['log'](_0x466a3f(0xd6),_0x59379['length']),_0x59379['length']>0x0?(_0x1277b6['parameters']['actions']=_0x59379,console[_0x466a3f(0xd9)](_0x466a3f(0x12f))):console[_0x466a3f(0xd9)](_0x466a3f(0xcd));}else{if(_0x486a7f['type']===COMMAND_FORMATS[_0x466a3f(0xf8)]||_0x486a7f[_0x466a3f(0x11a)]===COMMAND_FORMATS[_0x466a3f(0x10b)]){_0x1277b6['parameters']={..._0x486a7f[_0x466a3f(0xee)]};if(_0x486a7f['actions']&&Array['isArray'](_0x486a7f['actions'])){_0x1277b6['parameters']['actions']=_0x486a7f['actions'];if(_0x486a7f[_0x466a3f(0xb7)]===TOOL_IDS['AGENT_COMMUNICATION']&&_0x486a7f['actions'][_0x466a3f(0xf6)]>0x0){const _0xce673d=_0x486a7f['actions'][0x0];_0x1277b6['parameters'][_0x466a3f(0xbf)]=_0xce673d['type']||_0xce673d[_0x466a3f(0xbf)],Object[_0x466a3f(0x12e)](_0x1277b6[_0x466a3f(0xee)],_0xce673d);}}}}return _0x1277b6;}[a0_0x3c3855(0xda)](_0xb6e254){const _0x161455=a0_0x3c3855,_0x481993=[_0x161455(0xc4),'read',_0x161455(0xe1),_0x161455(0xc5),'move','append','create-dir',_0x161455(0x12d),'exists',_0x161455(0xc6),_0x161455(0xc0),'cd','pwd',_0x161455(0x110),'change-directory',_0x161455(0xca),'get-working-directory','pause-duration',_0x161455(0x10c),'action',_0x161455(0x102),_0x161455(0x109),_0x161455(0xf0),'taskId',_0x161455(0xc9),_0x161455(0xe7),_0x161455(0xfc),_0x161455(0xde),'parentTaskId','timeframe','templateId',_0x161455(0xe2),_0x161455(0xc8),'notes',_0x161455(0xb5),'selector','text','screenshot',_0x161455(0x13a),_0x161455(0x115),'message','conversation-id','prompt','output-path',_0x161455(0x10e),'quality','model',_0x161455(0x137),'image',_0x161455(0xe4),_0x161455(0xfe),_0x161455(0x140),'name','value',_0x161455(0x11a),'target'];return _0x481993['includes'](_0xb6e254)&&this[_0x161455(0xb4)](_0xb6e254);}['containsOnlyValidChars'](_0x5d575c){const _0x240bf9=a0_0x3c3855;if(!_0x5d575c||_0x5d575c[_0x240bf9(0xf6)]===0x0)return![];const _0x46da47=_0x5d575c[_0x240bf9(0xba)](0x0),_0x189530=_0x46da47>='a'&&_0x46da47<='z'||_0x46da47>='A'&&_0x46da47<='Z';if(!_0x189530)return![];for(let _0x564ae9=0x1;_0x564ae9<_0x5d575c['length'];_0x564ae9++){const _0x2c321b=_0x5d575c['charAt'](_0x564ae9),_0xa37803=_0x2c321b>='a'&&_0x2c321b<='z'||_0x2c321b>='A'&&_0x2c321b<='Z',_0x2d3430=_0x2c321b>='0'&&_0x2c321b<='9',_0x3e2c3f=_0x2c321b==='-';if(!_0xa37803&&!_0x2d3430&&!_0x3e2c3f)return![];}return!![];}[a0_0x3c3855(0x11f)](_0x3c0743){const _0x53525d=a0_0x3c3855,_0x4ec754=[_0x53525d(0xc4),'read','delete',_0x53525d(0xc5),'move',_0x53525d(0x10d),_0x53525d(0x141),_0x53525d(0x12d),'exists',_0x53525d(0xc6),'run-command','cd',_0x53525d(0x105),'create-directory',_0x53525d(0x123),'list-directory',_0x53525d(0x120),'pause-duration','reason','action',_0x53525d(0x102),'description','priority','taskId','status',_0x53525d(0xe7),_0x53525d(0xfc),_0x53525d(0xde),_0x53525d(0xf9),_0x53525d(0xb3),'templateId',_0x53525d(0xe2),'milestone',_0x53525d(0x130),_0x53525d(0xb5),'selector',_0x53525d(0xf3),'screenshot','element','recipient',_0x53525d(0xc3),_0x53525d(0x139),_0x53525d(0xbc),_0x53525d(0x118),_0x53525d(0x10e),_0x53525d(0x12c),_0x53525d(0x11b),_0x53525d(0x137),'image',_0x53525d(0xe4),'path','content','name',_0x53525d(0xcf),_0x53525d(0x11a),_0x53525d(0x124)];return _0x4ec754[_0x53525d(0x133)](_0x3c0743);}[a0_0x3c3855(0xce)](_0x37f968){const _0x7182b=a0_0x3c3855;return _0x37f968[_0x7182b(0x101)](/[-_](.)/g,(_0x167e03,_0x5d81b3)=>_0x5d81b3[_0x7182b(0xb8)]());}static['extractBetweenTags'](_0x58dd30,_0x273f11,_0x36193c){const _0x49cba4=a0_0x3c3855,_0x37592a=[];let _0x2b6de5=0x0;while(!![]){const _0x417717=_0x58dd30['indexOf'](_0x273f11,_0x2b6de5);if(_0x417717===-0x1)break;const _0x2e2173=_0x58dd30[_0x49cba4(0xe3)](_0x36193c,_0x417717+_0x273f11[_0x49cba4(0xf6)]);if(_0x2e2173===-0x1)break;const _0x2d2824=_0x58dd30['substring'](_0x417717+_0x273f11[_0x49cba4(0xf6)],_0x2e2173);_0x37592a[_0x49cba4(0xbb)]({'content':_0x2d2824,'fullMatch':_0x58dd30['substring'](_0x417717,_0x2e2173+_0x36193c['length']),'startIndex':_0x417717,'endIndex':_0x2e2173+_0x36193c['length']}),_0x2b6de5=_0x2e2173+_0x36193c[_0x49cba4(0xf6)];}return _0x37592a;}['cleanContent'](_0x56b32e){const _0x4c4978=a0_0x3c3855;let _0x5c03f1=_0x56b32e;return _0x5c03f1=_0x5c03f1['replace'](this[_0x4c4978(0x142)]['toolCommand'],''),_0x5c03f1=_0x5c03f1['replace'](this['patterns']['agentRedirect'],''),_0x5c03f1=_0x5c03f1[_0x4c4978(0x101)](this['patterns'][_0x4c4978(0x128)],(_0x283757,_0x2625fd)=>{const _0x216d04=_0x4c4978;try{const _0x5e18f7=JSON['parse'](_0x2625fd);if(this[_0x216d04(0xdf)](_0x5e18f7)||_0x5e18f7[_0x216d04(0xd4)]&&Array['isArray'](_0x5e18f7[_0x216d04(0xd4)]))return'';}catch{}return _0x283757;}),_0x5c03f1=_0x5c03f1['replace'](/\n\s*\n\s*\n/g,'\x0a\x0a'),_0x5c03f1=_0x5c03f1[_0x4c4978(0x104)](),_0x5c03f1;}}export default TagParser;function a0_0x1def(){const _0x250325=['ugXHAw4GsLnptIbKzxrLy3rLzcaTihnOB3vSzcb1C2uGygbGANnVBIbIBg9JA3m','A2v5CW','vgfNugfYC2vYierfqLvhoIbWCM9JzxnZAw5NifHntcbWyxjHBwv0zxi6','w1Hntf9ut09mx1jftu9wruq6','mta1odqYtuTzrvDH','y29UDgvUDa','y3jLyxrLlwrPCG','Cgf0DgvYBNm','zxH0CMfJDfrHz3nxAxrOqxr0CMLIDxrLCW','twLZC2LUzYbWyxjHBwv0zxjZig9YigfJDgLVBNm','yxr0CMLIDxrLCW','C3vIC3rYAw5N','vgfNugfYC2vYierfqLvhoIbTyxbWzwqGj2nVBNrLBNqNihrVicC','DgLTzwzYyw1L','y29UDgfPBNnpBMX5vMfSAwrdAgfYCW','DxjS','Dhj1zq','Dg9VBeLK','Dg9vChbLCKnHC2u','ywn0Aw9UCW','y2HHCKf0','ChvZAa','ChjVBxb0','BgfZDeLUzgv4','wY90B29Sxq','ywn0Aw9U','CNvUlwnVBw1HBMq','twLZC2LUzYbQC29Urgf0ysbMB3iGsLnptIbJB21Tyw5K','CgfYC2vytuXqyxjHBwv0zxjZ','BwvZC2fNzq','D3jPDgu','y29WEq','C3rHDhm','zxH0CMfJDefNzw50uMvKAxjLy3rZ','BwLSzxn0B25L','C3rHDhvZ','BgLZDc1KAxjLy3rVCNK','ndy3mtmXwfv1sejA','we1m','vgfNugfYC2vYierfqLvhoIbxqvjosu5hic0GBM8Gywn0Aw9UCYbJCMvHDgvKlcb0AgLZihDPBgWGy2f1C2uGiMfJDgLVBNmGAxmGBM90igL0zxjHyMXLiIbLCNjVCG','x3rVq2fTzwXdyxnL','DMfSDwu','ywDLBNrKzwXHEq','ygbGANnVBG','Dg9VBenVBw1HBMq','CgfYC2u','Dg9VBenVBw1HBMrZ','uKvrvuLsrvnFuKvtue9ou0u','vgfNugfYC2vYierfqLvhoIb0B3rHBcbHy3rPB25ZignYzwf0zwq6','nePvr3jcEq','u1rbtKrbuKq','Bg9N','AxnwywXPzfHTBfrHz05HBwu','ANnVBKrHDge','zgvJB2rLshrTBevUDgL0AwvZ','DMfSAwrHDgvuB29Sq29TBwfUza','CMvSyxrLzfrV','AxnuB29Sq29TBwfUzePtt04','zMLSzxn5C3rLBq','zgvSzxrL','C3rHz2u','Aw5KzxHpzG','y29TBwfUza','nJa3otHtrejzsfC','B2jQzwn0','zgvWzw5KC09U','ndu4nJKWBevHuLPM','AgfZt3DUuhjVCgvYDhK','CMvTB3zLvg9VBeLUDM9JyxrPB25cBg9JA3m','z3jVDxbZ','vvjhru5u','CgfYC2vbDhrYAwj1DgvZ','CgfYyw1LDgvYCW','vgfNugfYC2vYierfqLvhoIbUB3jTywXPEMLUzYbytuWGy29TBwfUzcb3AxrOihbHCMfTzxrLCNm6','ChjPB3jPDhK','ihrVB2W','zw5KC1DPDgG','Dgv4Da','vgfNugfYC2vYierfqLvhoIbLEhrYywn0qNjHy2TLDe5VDgf0Aw9Uvg9VBhmGlsbMB3vUzca','mtKWsKLlENfX','BgvUz3rO','w0Ptt05Fq09erv9cte9ds19sru1pvKvexq','sLnptG','CgfYzw50vgfZA0LK','Bwf0y2HbBgW','Dg9VBa','zgvWzw5Kzw5JEvr5Cgu','Aw1Hz2uTz2vU','Cgf0Aa','Aw5MzxjuB29SrNjVBufJDgLVBNm','ntGWnZaYmfr4vezqCG','CMvWBgfJzq','DgL0Bgu','D2L0AcbKyxrHoG','DhjPBq','ChDK','vgfNugfYC2vYierfqLvhoIbRzwvWAw5NigfJDgLVBIb0ExbLicC','y2fSBa','zxH0CMfJDfrVB2XcEu5HBwu','zgvZy3jPChrPB24','reLsrunux0fdveLptG','sLnptL9qtefjtG','CMvHC29U','yxbWzw5K','C2L6zq','mtq2ndi0nK5WtKfvzW','y3jLyxrLlwrPCMvJDg9YEq','zMLSzvbHDgG','Dw5RBM93BG','ofPUzKPyqG','AxnbCNjHEq','CMvJAxbPzw50','zxH0CMfJDfbSywLUsLnptG','zxHLyW','B3v0Chv0lxbHDgG','mtmYodu4m29Rr3vkzG','DhLWzq','Bw9KzwW','zxH0CMfJDerPCMvJDfrVB2XuywDZ','Cgf1C2uTzhvYyxrPB24','zxH0CMfJDejYywnRzxroB3rHDgLVBLrVB2XZ','AxnuywDjBLzHBgLKtgLZDa','z2v0lxDVCMTPBMCTzgLYzwn0B3j5','Bwf0y2G','x3zHBhvL','y2HHBMDLlwrPCMvJDg9YEq','DgfYz2v0','vgfNugfYC2vYierfqLvhoIbtA2LWCgLUzYbWBgfPBIbku09oic0Gy291BgqGBM90igrLDgvYBwLUzsb2ywXPzcb0B29Sswq','AM9Izg9Uzq','zw50CMLLCW','ANnVBKjSB2nR','ywDLBNrszwrPCMvJDa','y291BNq6','zxH0CMfJDePtt05dB2rLqMXVy2TZ','CxvHBgL0Eq','BgLZDa','yxnZAwDU','vgfNugfYC2vYierfqLvhoIbHzgrLzcbHy3rPB25ZigfYCMf5ihrVihbHCMfTzxrLCNm','BM90zxm','DgvYBwLUywW','yNjVD3nLCG','Aw5JBhvKzxm','ywDLBNrJB21TDw5Py2f0Aw9U','ygbG','qunusu9ou19buLjbwq','yMf0y2G','zxH0CMfJDenVBNrLBNq','y29UDMvYC2f0Aw9UlwLK','zwXLBwvUDa'];a0_0x1def=function(){return _0x250325;};return a0_0x1def();}