@push.rocks/smartagent 1.8.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist_ts/00_commitinfo_data.js +3 -3
  2. package/dist_ts/index.d.ts +8 -14
  3. package/dist_ts/index.js +8 -24
  4. package/dist_ts/plugins.d.ts +8 -9
  5. package/dist_ts/plugins.js +10 -12
  6. package/dist_ts/smartagent.classes.agent.d.ts +2 -0
  7. package/dist_ts/smartagent.classes.agent.js +173 -0
  8. package/dist_ts/smartagent.classes.toolregistry.d.ts +7 -70
  9. package/dist_ts/smartagent.classes.toolregistry.js +11 -155
  10. package/dist_ts/smartagent.interfaces.d.ts +47 -283
  11. package/dist_ts/smartagent.interfaces.js +6 -7
  12. package/dist_ts/smartagent.utils.truncation.d.ts +10 -0
  13. package/dist_ts/smartagent.utils.truncation.js +26 -0
  14. package/dist_ts_compaction/index.d.ts +1 -0
  15. package/dist_ts_compaction/index.js +2 -0
  16. package/dist_ts_compaction/plugins.d.ts +4 -0
  17. package/dist_ts_compaction/plugins.js +3 -0
  18. package/dist_ts_compaction/smartagent.compaction.d.ts +10 -0
  19. package/dist_ts_compaction/smartagent.compaction.js +46 -0
  20. package/dist_ts_tools/index.d.ts +8 -0
  21. package/dist_ts_tools/index.js +6 -0
  22. package/dist_ts_tools/plugins.d.ts +15 -0
  23. package/dist_ts_tools/plugins.js +19 -0
  24. package/dist_ts_tools/tool.filesystem.d.ts +6 -0
  25. package/dist_ts_tools/tool.filesystem.js +102 -0
  26. package/dist_ts_tools/tool.http.d.ts +2 -0
  27. package/dist_ts_tools/tool.http.js +65 -0
  28. package/dist_ts_tools/tool.json.d.ts +2 -0
  29. package/dist_ts_tools/tool.json.js +47 -0
  30. package/dist_ts_tools/tool.shell.d.ts +8 -0
  31. package/dist_ts_tools/tool.shell.js +40 -0
  32. package/npmextra.json +1 -1
  33. package/package.json +30 -18
  34. package/readme.hints.md +38 -84
  35. package/readme.md +254 -682
  36. package/ts/00_commitinfo_data.ts +2 -2
  37. package/ts/index.ts +10 -37
  38. package/ts/plugins.ts +22 -21
  39. package/ts/smartagent.classes.agent.ts +198 -0
  40. package/ts/smartagent.classes.toolregistry.ts +11 -179
  41. package/ts/smartagent.interfaces.ts +51 -363
  42. package/ts/smartagent.utils.truncation.ts +39 -0
  43. package/ts_compaction/index.ts +1 -0
  44. package/ts_compaction/plugins.ts +6 -0
  45. package/ts_compaction/smartagent.compaction.ts +51 -0
  46. package/ts_tools/index.ts +8 -0
  47. package/ts_tools/plugins.ts +30 -0
  48. package/ts_tools/tool.filesystem.ts +131 -0
  49. package/ts_tools/tool.http.ts +78 -0
  50. package/ts_tools/tool.json.ts +53 -0
  51. package/ts_tools/tool.shell.ts +62 -0
  52. package/dist_ts/smartagent.classes.driveragent.d.ts +0 -134
  53. package/dist_ts/smartagent.classes.driveragent.js +0 -671
  54. package/dist_ts/smartagent.classes.dualagent.d.ts +0 -93
  55. package/dist_ts/smartagent.classes.dualagent.js +0 -614
  56. package/dist_ts/smartagent.classes.guardianagent.d.ts +0 -46
  57. package/dist_ts/smartagent.classes.guardianagent.js +0 -201
  58. package/dist_ts/smartagent.tools.base.d.ts +0 -52
  59. package/dist_ts/smartagent.tools.base.js +0 -42
  60. package/dist_ts/smartagent.tools.browser.d.ts +0 -17
  61. package/dist_ts/smartagent.tools.browser.js +0 -229
  62. package/dist_ts/smartagent.tools.deno.d.ts +0 -21
  63. package/dist_ts/smartagent.tools.deno.js +0 -191
  64. package/dist_ts/smartagent.tools.expert.d.ts +0 -27
  65. package/dist_ts/smartagent.tools.expert.js +0 -126
  66. package/dist_ts/smartagent.tools.filesystem.d.ts +0 -40
  67. package/dist_ts/smartagent.tools.filesystem.js +0 -801
  68. package/dist_ts/smartagent.tools.http.d.ts +0 -16
  69. package/dist_ts/smartagent.tools.http.js +0 -264
  70. package/dist_ts/smartagent.tools.json.d.ts +0 -24
  71. package/dist_ts/smartagent.tools.json.js +0 -202
  72. package/dist_ts/smartagent.tools.search.d.ts +0 -29
  73. package/dist_ts/smartagent.tools.search.js +0 -215
  74. package/dist_ts/smartagent.tools.shell.d.ts +0 -17
  75. package/dist_ts/smartagent.tools.shell.js +0 -202
  76. package/ts/smartagent.classes.driveragent.ts +0 -775
  77. package/ts/smartagent.classes.dualagent.ts +0 -692
  78. package/ts/smartagent.classes.guardianagent.ts +0 -241
  79. package/ts/smartagent.tools.base.ts +0 -83
  80. package/ts/smartagent.tools.browser.ts +0 -253
  81. package/ts/smartagent.tools.deno.ts +0 -230
  82. package/ts/smartagent.tools.expert.ts +0 -144
  83. package/ts/smartagent.tools.filesystem.ts +0 -885
  84. package/ts/smartagent.tools.http.ts +0 -283
  85. package/ts/smartagent.tools.json.ts +0 -224
  86. package/ts/smartagent.tools.search.ts +0 -237
  87. package/ts/smartagent.tools.shell.ts +0 -230
@@ -1,671 +0,0 @@
1
- import * as plugins from './plugins.js';
2
- import * as interfaces from './smartagent.interfaces.js';
3
- /**
4
- * DriverAgent - Executes tasks by reasoning and proposing tool calls
5
- * Works in conjunction with GuardianAgent for approval
6
- */
7
- export class DriverAgent {
8
- provider;
9
- systemMessage;
10
- maxHistoryMessages;
11
- messageHistory = [];
12
- tools = new Map();
13
- onToken;
14
- isInThinkingMode = false; // Track thinking/content state for markers
15
- constructor(provider, options) {
16
- this.provider = provider;
17
- // Support both legacy string systemMessage and new options object
18
- if (typeof options === 'string') {
19
- this.systemMessage = options || this.getDefaultSystemMessage();
20
- this.maxHistoryMessages = 20;
21
- }
22
- else {
23
- this.systemMessage = options?.systemMessage || this.getDefaultSystemMessage();
24
- this.maxHistoryMessages = options?.maxHistoryMessages ?? 20;
25
- this.onToken = options?.onToken;
26
- }
27
- }
28
- /**
29
- * Set the token callback for streaming mode
30
- * @param callback Function to call for each generated token
31
- */
32
- setOnToken(callback) {
33
- this.onToken = callback;
34
- }
35
- /**
36
- * Register a tool for use by the driver
37
- */
38
- registerTool(tool) {
39
- this.tools.set(tool.name, tool);
40
- }
41
- /**
42
- * Get all registered tools
43
- */
44
- getTools() {
45
- return this.tools;
46
- }
47
- /**
48
- * Initialize a new conversation for a task
49
- * @param task The task description
50
- * @param images Optional base64-encoded images for vision tasks
51
- */
52
- async startTask(task, images) {
53
- // Reset message history
54
- this.messageHistory = [];
55
- // Build the user message based on available tools
56
- const hasTools = this.tools.size > 0;
57
- let userMessage;
58
- if (hasTools) {
59
- userMessage = `TASK: ${task}\n\nAnalyze this task and determine what actions are needed. If you need to use a tool, provide a tool call proposal.`;
60
- }
61
- else {
62
- userMessage = `TASK: ${task}\n\nComplete this task directly. When done, wrap your final output in <task_complete>your output here</task_complete> tags.`;
63
- }
64
- // Add to history
65
- this.messageHistory.push({
66
- role: 'user',
67
- content: userMessage,
68
- });
69
- // Build the system message - adapt based on available tools
70
- let fullSystemMessage;
71
- if (hasTools) {
72
- const toolDescriptions = this.buildToolDescriptions();
73
- fullSystemMessage = `${this.systemMessage}\n\n## Available Tools\n${toolDescriptions}`;
74
- }
75
- else {
76
- // Use a simpler system message when no tools are available
77
- fullSystemMessage = this.getNoToolsSystemMessage();
78
- }
79
- // Get response from provider - use streaming if available and callback is set
80
- let response;
81
- if (this.onToken && typeof this.provider.chatStreaming === 'function') {
82
- // Use streaming mode with token callback
83
- response = await this.provider.chatStreaming({
84
- systemMessage: fullSystemMessage,
85
- userMessage: userMessage,
86
- messageHistory: [],
87
- images: images,
88
- onToken: this.onToken,
89
- });
90
- }
91
- else {
92
- // Fallback to non-streaming mode
93
- response = await this.provider.chat({
94
- systemMessage: fullSystemMessage,
95
- userMessage: userMessage,
96
- messageHistory: [],
97
- images: images,
98
- });
99
- }
100
- // Add assistant response to history (store images if provided, preserve reasoning for GPT-OSS)
101
- const historyMessage = {
102
- role: 'assistant',
103
- content: response.message,
104
- reasoning: response.reasoning,
105
- };
106
- this.messageHistory.push(historyMessage);
107
- return {
108
- role: 'assistant',
109
- content: response.message,
110
- };
111
- }
112
- /**
113
- * Continue the conversation with feedback or results
114
- */
115
- async continueWithMessage(message) {
116
- // Add the new message to history
117
- this.messageHistory.push({
118
- role: 'user',
119
- content: message,
120
- });
121
- // Build the system message - adapt based on available tools
122
- const hasTools = this.tools.size > 0;
123
- let fullSystemMessage;
124
- if (hasTools) {
125
- const toolDescriptions = this.buildToolDescriptions();
126
- fullSystemMessage = `${this.systemMessage}\n\n## Available Tools\n${toolDescriptions}`;
127
- }
128
- else {
129
- fullSystemMessage = this.getNoToolsSystemMessage();
130
- }
131
- // Get response from provider with history windowing
132
- // Keep original task and most recent messages to avoid token explosion
133
- let historyForChat;
134
- const fullHistory = this.messageHistory.slice(0, -1); // Exclude the just-added message
135
- if (this.maxHistoryMessages > 0 && fullHistory.length > this.maxHistoryMessages) {
136
- // Keep the original task (first message) and most recent messages
137
- historyForChat = [
138
- fullHistory[0], // Original task
139
- ...fullHistory.slice(-(this.maxHistoryMessages - 1)), // Recent messages
140
- ];
141
- }
142
- else {
143
- historyForChat = fullHistory;
144
- }
145
- // Get response from provider - use streaming if available and callback is set
146
- let response;
147
- if (this.onToken && typeof this.provider.chatStreaming === 'function') {
148
- // Use streaming mode with token callback
149
- response = await this.provider.chatStreaming({
150
- systemMessage: fullSystemMessage,
151
- userMessage: message,
152
- messageHistory: historyForChat,
153
- onToken: this.onToken,
154
- });
155
- }
156
- else {
157
- // Fallback to non-streaming mode
158
- response = await this.provider.chat({
159
- systemMessage: fullSystemMessage,
160
- userMessage: message,
161
- messageHistory: historyForChat,
162
- });
163
- }
164
- // Add assistant response to history (preserve reasoning for GPT-OSS)
165
- this.messageHistory.push({
166
- role: 'assistant',
167
- content: response.message,
168
- reasoning: response.reasoning,
169
- });
170
- return {
171
- role: 'assistant',
172
- content: response.message,
173
- };
174
- }
175
- /**
176
- * Parse tool call proposals from assistant response
177
- */
178
- parseToolCallProposals(response) {
179
- const proposals = [];
180
- // Match <tool_call>...</tool_call> blocks
181
- const toolCallRegex = /<tool_call>([\s\S]*?)<\/tool_call>/g;
182
- let match;
183
- while ((match = toolCallRegex.exec(response)) !== null) {
184
- const content = match[1];
185
- try {
186
- const proposal = this.parseToolCallContent(content);
187
- if (proposal) {
188
- proposals.push(proposal);
189
- }
190
- }
191
- catch (error) {
192
- // Skip malformed tool calls
193
- console.warn('Failed to parse tool call:', error);
194
- }
195
- }
196
- return proposals;
197
- }
198
- /**
199
- * Parse the content inside a tool_call block
200
- */
201
- parseToolCallContent(content) {
202
- // Extract tool name
203
- const toolMatch = content.match(/<tool>(.*?)<\/tool>/s);
204
- if (!toolMatch)
205
- return null;
206
- const toolName = toolMatch[1].trim();
207
- // Extract action
208
- const actionMatch = content.match(/<action>(.*?)<\/action>/s);
209
- if (!actionMatch)
210
- return null;
211
- const action = actionMatch[1].trim();
212
- // Extract params (JSON)
213
- const paramsMatch = content.match(/<params>([\s\S]*?)<\/params>/);
214
- let params = {};
215
- if (paramsMatch) {
216
- try {
217
- params = JSON.parse(paramsMatch[1].trim());
218
- }
219
- catch {
220
- // Try to extract individual parameters if JSON fails
221
- params = this.extractParamsFromXml(paramsMatch[1]);
222
- }
223
- }
224
- // Extract reasoning (optional)
225
- const reasoningMatch = content.match(/<reasoning>([\s\S]*?)<\/reasoning>/);
226
- const reasoning = reasoningMatch ? reasoningMatch[1].trim() : undefined;
227
- return {
228
- proposalId: this.generateProposalId(),
229
- toolName,
230
- action,
231
- params,
232
- reasoning,
233
- };
234
- }
235
- /**
236
- * Extract parameters from XML-like format when JSON parsing fails
237
- */
238
- extractParamsFromXml(content) {
239
- const params = {};
240
- const paramRegex = /<(\w+)>([\s\S]*?)<\/\1>/g;
241
- let match;
242
- while ((match = paramRegex.exec(content)) !== null) {
243
- const key = match[1];
244
- let value = match[2].trim();
245
- // Try to parse as JSON for arrays/objects
246
- try {
247
- value = JSON.parse(value);
248
- }
249
- catch {
250
- // Keep as string if not valid JSON
251
- }
252
- params[key] = value;
253
- }
254
- return params;
255
- }
256
- /**
257
- * Check if the response indicates task completion
258
- */
259
- isTaskComplete(response) {
260
- // Check for explicit completion markers
261
- const completionMarkers = [
262
- '<task_complete>',
263
- '<task_completed>',
264
- 'TASK COMPLETE',
265
- 'Task completed successfully',
266
- ];
267
- const lowerResponse = response.toLowerCase();
268
- return completionMarkers.some(marker => lowerResponse.includes(marker.toLowerCase()));
269
- }
270
- /**
271
- * Check if the response needs clarification or user input
272
- */
273
- needsClarification(response) {
274
- const clarificationMarkers = [
275
- '<needs_clarification>',
276
- '<question>',
277
- 'please clarify',
278
- 'could you specify',
279
- 'what do you mean by',
280
- ];
281
- const lowerResponse = response.toLowerCase();
282
- return clarificationMarkers.some(marker => lowerResponse.includes(marker.toLowerCase()));
283
- }
284
- /**
285
- * Extract the final result from a completed task
286
- */
287
- extractTaskResult(response) {
288
- // Try to extract from result tags
289
- const resultMatch = response.match(/<task_result>([\s\S]*?)<\/task_result>/);
290
- if (resultMatch) {
291
- return resultMatch[1].trim();
292
- }
293
- const completeMatch = response.match(/<task_complete>([\s\S]*?)<\/task_complete>/);
294
- if (completeMatch) {
295
- return completeMatch[1].trim();
296
- }
297
- return null;
298
- }
299
- /**
300
- * Build tool descriptions for the system message
301
- */
302
- buildToolDescriptions() {
303
- const descriptions = [];
304
- for (const tool of this.tools.values()) {
305
- descriptions.push(tool.getFullDescription());
306
- }
307
- return descriptions.join('\n\n');
308
- }
309
- /**
310
- * Generate a unique proposal ID
311
- */
312
- generateProposalId() {
313
- return `prop_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
314
- }
315
- /**
316
- * Get the default system message for the driver
317
- */
318
- getDefaultSystemMessage() {
319
- return `You are an AI assistant that executes tasks by using available tools.
320
-
321
- ## Your Role
322
- You analyze tasks, break them down into steps, and use tools to accomplish goals.
323
-
324
- ## CRITICAL: Tool Usage Format
325
- To use a tool, you MUST literally write out the XML tags in your response. The system parses your output looking for these exact tags. Do NOT just describe or mention the tool call - you must OUTPUT the actual XML.
326
-
327
- CORRECT (the XML is in the output):
328
- <tool_call>
329
- <tool>json</tool>
330
- <action>validate</action>
331
- <params>{"jsonString": "{\\"key\\":\\"value\\"}"}</params>
332
- </tool_call>
333
-
334
- WRONG (just describing, no actual XML):
335
- "I will call json.validate now" or "Let me use the tool"
336
-
337
- ## Guidelines
338
- 1. Think step by step about what needs to be done
339
- 2. When you need a tool, OUTPUT the <tool_call> XML tags - do not just mention them
340
- 3. Only propose ONE tool call at a time
341
- 4. Wait for the result before proposing the next action
342
- 5. When the task is complete, OUTPUT:
343
-
344
- <task_complete>
345
- Your final result here
346
- </task_complete>
347
-
348
- ## Important
349
- - The <tool_call> and <task_complete> tags MUST appear literally in your response
350
- - If you just say "I'll call the tool" without the actual XML, it will NOT work
351
- - If you need clarification, ask using <needs_clarification>your question</needs_clarification>`;
352
- }
353
- /**
354
- * Get the system message when no tools are available
355
- * Used for direct task completion without tool usage
356
- */
357
- getNoToolsSystemMessage() {
358
- // Use custom system message if provided, otherwise use a simple default
359
- if (this.systemMessage && this.systemMessage !== this.getDefaultSystemMessage()) {
360
- return this.systemMessage;
361
- }
362
- return `You are an AI assistant that completes tasks directly.
363
-
364
- ## Your Role
365
- You analyze tasks and provide complete, high-quality outputs.
366
-
367
- ## Output Format
368
- When you have completed the task, wrap your final output in task_complete tags:
369
-
370
- <task_complete>
371
- Your complete output here
372
- </task_complete>
373
-
374
- ## Guidelines
375
- 1. Analyze the task requirements carefully
376
- 2. Provide a complete and accurate response
377
- 3. Always wrap your final output in <task_complete></task_complete> tags
378
- 4. If you need clarification, ask using <needs_clarification>your question</needs_clarification>`;
379
- }
380
- /**
381
- * Reset the conversation state
382
- */
383
- reset() {
384
- this.messageHistory = [];
385
- }
386
- // ================================
387
- // Native Tool Calling Support
388
- // ================================
389
- /**
390
- * Start a task with native tool calling support
391
- * Uses Ollama's native tool calling API instead of XML parsing
392
- * @param task The task description
393
- * @param images Optional base64-encoded images for vision tasks
394
- * @returns Response with content, reasoning, and any tool calls
395
- */
396
- async startTaskWithNativeTools(task, images) {
397
- // Reset message history
398
- this.messageHistory = [];
399
- // Build simple user message (no XML instructions needed for native tool calling)
400
- const userMessage = `TASK: ${task}\n\nComplete this task using the available tools. When done, provide your final output.`;
401
- // Add to history
402
- this.messageHistory.push({
403
- role: 'user',
404
- content: userMessage,
405
- });
406
- // Build system message for native tool calling
407
- const fullSystemMessage = this.getNativeToolsSystemMessage();
408
- // Get tools in JSON schema format
409
- const tools = this.getToolsAsJsonSchema();
410
- // Check if provider supports native tool calling (Ollama)
411
- const provider = this.provider;
412
- if (typeof provider.collectStreamResponse !== 'function') {
413
- throw new Error('Provider does not support native tool calling. Use startTask() instead.');
414
- }
415
- // Use collectStreamResponse for streaming support with tools
416
- const response = await provider.collectStreamResponse({
417
- systemMessage: fullSystemMessage,
418
- userMessage: userMessage,
419
- messageHistory: [],
420
- images: images,
421
- tools: tools.length > 0 ? tools : undefined,
422
- },
423
- // Pass onToken callback through onChunk for streaming with thinking markers
424
- this.onToken ? (chunk) => {
425
- if (chunk.thinking && this.onToken) {
426
- // Add marker only when transitioning INTO thinking mode
427
- if (!this.isInThinkingMode) {
428
- this.onToken('\n[THINKING] ');
429
- this.isInThinkingMode = true;
430
- }
431
- this.onToken(chunk.thinking);
432
- }
433
- if (chunk.content && this.onToken) {
434
- // Add marker when transitioning OUT of thinking mode
435
- if (this.isInThinkingMode) {
436
- this.onToken('\n[OUTPUT] ');
437
- this.isInThinkingMode = false;
438
- }
439
- this.onToken(chunk.content);
440
- }
441
- } : undefined);
442
- // Reset thinking state after response completes
443
- this.isInThinkingMode = false;
444
- // Add assistant response to history
445
- const historyMessage = {
446
- role: 'assistant',
447
- content: response.message || '',
448
- reasoning: response.thinking || response.reasoning,
449
- };
450
- // CRITICAL: Preserve tool_calls in history for native tool calling
451
- // Without this, the model doesn't know it already called a tool and loops forever
452
- if (response.toolCalls && response.toolCalls.length > 0) {
453
- historyMessage.tool_calls = response.toolCalls.map((tc) => ({
454
- function: {
455
- name: tc.function.name,
456
- arguments: tc.function.arguments,
457
- },
458
- }));
459
- }
460
- this.messageHistory.push(historyMessage);
461
- // Convert Ollama tool calls to our format
462
- let toolCalls;
463
- if (response.toolCalls && response.toolCalls.length > 0) {
464
- toolCalls = response.toolCalls.map((tc) => ({
465
- function: {
466
- name: tc.function.name,
467
- arguments: tc.function.arguments,
468
- index: tc.function.index,
469
- },
470
- }));
471
- }
472
- return {
473
- message: {
474
- role: 'assistant',
475
- content: response.message || '',
476
- },
477
- toolCalls,
478
- };
479
- }
480
- /**
481
- * Continue conversation with native tool calling support
482
- * @param message The message to continue with (e.g., tool result)
483
- * @param toolName Optional tool name - when provided, message is added as role: 'tool' instead of 'user'
484
- * @returns Response with content, reasoning, and any tool calls
485
- */
486
- async continueWithNativeTools(message, toolName) {
487
- // Add the new message to history
488
- if (toolName) {
489
- // Tool result - must use role: 'tool' for native tool calling
490
- // The 'tool' role is supported by providers but not in the ChatMessage type
491
- this.messageHistory.push({
492
- role: 'tool',
493
- content: message,
494
- toolName: toolName,
495
- });
496
- }
497
- else {
498
- // Regular user message
499
- this.messageHistory.push({
500
- role: 'user',
501
- content: message,
502
- });
503
- }
504
- // Build system message
505
- const fullSystemMessage = this.getNativeToolsSystemMessage();
506
- // Get tools in JSON schema format
507
- const tools = this.getToolsAsJsonSchema();
508
- // Get response from provider with history windowing
509
- // For tool results, include the full history (with tool message)
510
- // For regular user messages, exclude the last message (it becomes userMessage)
511
- let historyForChat;
512
- const fullHistory = toolName
513
- ? this.messageHistory // Include tool result in history
514
- : this.messageHistory.slice(0, -1); // Exclude last user message
515
- if (this.maxHistoryMessages > 0 && fullHistory.length > this.maxHistoryMessages) {
516
- historyForChat = [
517
- fullHistory[0],
518
- ...fullHistory.slice(-(this.maxHistoryMessages - 1)),
519
- ];
520
- }
521
- else {
522
- historyForChat = fullHistory;
523
- }
524
- // Check if provider supports native tool calling
525
- const provider = this.provider;
526
- if (typeof provider.collectStreamResponse !== 'function') {
527
- throw new Error('Provider does not support native tool calling. Use continueWithMessage() instead.');
528
- }
529
- // For tool results, use a continuation prompt instead of repeating the result
530
- const userMessage = toolName
531
- ? 'Continue with the task. The tool result has been provided above.'
532
- : message;
533
- // Use collectStreamResponse for streaming support with tools
534
- const response = await provider.collectStreamResponse({
535
- systemMessage: fullSystemMessage,
536
- userMessage: userMessage,
537
- messageHistory: historyForChat,
538
- tools: tools.length > 0 ? tools : undefined,
539
- },
540
- // Pass onToken callback through onChunk for streaming with thinking markers
541
- this.onToken ? (chunk) => {
542
- if (chunk.thinking && this.onToken) {
543
- // Add marker only when transitioning INTO thinking mode
544
- if (!this.isInThinkingMode) {
545
- this.onToken('\n[THINKING] ');
546
- this.isInThinkingMode = true;
547
- }
548
- this.onToken(chunk.thinking);
549
- }
550
- if (chunk.content && this.onToken) {
551
- // Add marker when transitioning OUT of thinking mode
552
- if (this.isInThinkingMode) {
553
- this.onToken('\n[OUTPUT] ');
554
- this.isInThinkingMode = false;
555
- }
556
- this.onToken(chunk.content);
557
- }
558
- } : undefined);
559
- // Reset thinking state after response completes
560
- this.isInThinkingMode = false;
561
- // Add assistant response to history
562
- const historyMessage = {
563
- role: 'assistant',
564
- content: response.message || '',
565
- reasoning: response.thinking || response.reasoning,
566
- };
567
- // CRITICAL: Preserve tool_calls in history for native tool calling
568
- // Without this, the model doesn't know it already called a tool and loops forever
569
- if (response.toolCalls && response.toolCalls.length > 0) {
570
- historyMessage.tool_calls = response.toolCalls.map((tc) => ({
571
- function: {
572
- name: tc.function.name,
573
- arguments: tc.function.arguments,
574
- },
575
- }));
576
- }
577
- this.messageHistory.push(historyMessage);
578
- // Convert Ollama tool calls to our format
579
- let toolCalls;
580
- if (response.toolCalls && response.toolCalls.length > 0) {
581
- toolCalls = response.toolCalls.map((tc) => ({
582
- function: {
583
- name: tc.function.name,
584
- arguments: tc.function.arguments,
585
- index: tc.function.index,
586
- },
587
- }));
588
- }
589
- return {
590
- message: {
591
- role: 'assistant',
592
- content: response.message || '',
593
- },
594
- toolCalls,
595
- };
596
- }
597
- /**
598
- * Get system message for native tool calling mode
599
- * Simplified prompt that lets the model use tools naturally
600
- */
601
- getNativeToolsSystemMessage() {
602
- return `You are an AI assistant that executes tasks by using available tools.
603
-
604
- ## Your Role
605
- You analyze tasks, break them down into steps, and use tools to accomplish goals.
606
-
607
- ## Guidelines
608
- 1. Think step by step about what needs to be done
609
- 2. Use the available tools to complete the task
610
- 3. Process tool results and continue until the task is complete
611
- 4. When the task is complete, provide a final summary
612
-
613
- ## Important
614
- - Use tools when needed to gather information or perform actions
615
- - If you need clarification, ask the user
616
- - Always verify your work before marking the task complete`;
617
- }
618
- /**
619
- * Convert registered tools to Ollama JSON Schema format for native tool calling
620
- * Each tool action becomes a separate function with name format: "toolName_actionName"
621
- * @returns Array of IOllamaTool compatible tool definitions
622
- */
623
- getToolsAsJsonSchema() {
624
- const tools = [];
625
- for (const tool of this.tools.values()) {
626
- for (const action of tool.actions) {
627
- // Build the tool definition in Ollama format
628
- const toolDef = {
629
- type: 'function',
630
- function: {
631
- name: `${tool.name}_${action.name}`, // e.g., "json_validate"
632
- description: `[${tool.name}] ${action.description}`,
633
- parameters: action.parameters,
634
- },
635
- };
636
- tools.push(toolDef);
637
- }
638
- }
639
- return tools;
640
- }
641
- /**
642
- * Parse native tool calls from provider response into IToolCallProposal format
643
- * @param toolCalls Array of native tool calls from the provider
644
- * @returns Array of IToolCallProposal ready for execution
645
- */
646
- parseNativeToolCalls(toolCalls) {
647
- return toolCalls.map(tc => {
648
- // Split "json_validate" -> toolName="json", action="validate"
649
- const fullName = tc.function.name;
650
- const underscoreIndex = fullName.indexOf('_');
651
- let toolName;
652
- let action;
653
- if (underscoreIndex > 0) {
654
- toolName = fullName.substring(0, underscoreIndex);
655
- action = fullName.substring(underscoreIndex + 1);
656
- }
657
- else {
658
- // Fallback: treat entire name as tool name with empty action
659
- toolName = fullName;
660
- action = '';
661
- }
662
- return {
663
- proposalId: this.generateProposalId(),
664
- toolName,
665
- action,
666
- params: tc.function.arguments,
667
- };
668
- });
669
- }
670
- }
671
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhZ2VudC5jbGFzc2VzLmRyaXZlcmFnZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRhZ2VudC5jbGFzc2VzLmRyaXZlcmFnZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxVQUFVLE1BQU0sNEJBQTRCLENBQUM7QUFlekQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFdBQVc7SUFDZCxRQUFRLENBQWtDO0lBQzFDLGFBQWEsQ0FBUztJQUN0QixrQkFBa0IsQ0FBUztJQUMzQixjQUFjLEdBQWtDLEVBQUUsQ0FBQztJQUNuRCxLQUFLLEdBQWlDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDaEQsT0FBTyxDQUEyQjtJQUNsQyxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsQ0FBRSwyQ0FBMkM7SUFFOUUsWUFDRSxRQUF5QyxFQUN6QyxPQUFzQztRQUV0QyxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUV6QixrRUFBa0U7UUFDbEUsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNoQyxJQUFJLENBQUMsYUFBYSxHQUFHLE9BQU8sSUFBSSxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztZQUMvRCxJQUFJLENBQUMsa0JBQWtCLEdBQUcsRUFBRSxDQUFDO1FBQy9CLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLEVBQUUsYUFBYSxJQUFJLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1lBQzlFLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxPQUFPLEVBQUUsa0JBQWtCLElBQUksRUFBRSxDQUFDO1lBQzVELElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxFQUFFLE9BQU8sQ0FBQztRQUNsQyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFVBQVUsQ0FBQyxRQUFpQztRQUNqRCxJQUFJLENBQUMsT0FBTyxHQUFHLFFBQVEsQ0FBQztJQUMxQixDQUFDO0lBRUQ7O09BRUc7SUFDSSxZQUFZLENBQUMsSUFBcUI7UUFDdkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxRQUFRO1FBQ2IsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3BCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFZLEVBQUUsTUFBaUI7UUFDcEQsd0JBQXdCO1FBQ3hCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBRXpCLGtEQUFrRDtRQUNsRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7UUFDckMsSUFBSSxXQUFtQixDQUFDO1FBQ3hCLElBQUksUUFBUSxFQUFFLENBQUM7WUFDYixXQUFXLEdBQUcsU0FBUyxJQUFJLHVIQUF1SCxDQUFDO1FBQ3JKLENBQUM7YUFBTSxDQUFDO1lBQ04sV0FBVyxHQUFHLFNBQVMsSUFBSSw2SEFBNkgsQ0FBQztRQUMzSixDQUFDO1FBRUQsaUJBQWlCO1FBQ2pCLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDO1lBQ3ZCLElBQUksRUFBRSxNQUFNO1lBQ1osT0FBTyxFQUFFLFdBQVc7U0FDckIsQ0FBQyxDQUFDO1FBRUgsNERBQTREO1FBQzVELElBQUksaUJBQXlCLENBQUM7UUFDOUIsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDdEQsaUJBQWlCLEdBQUcsR0FBRyxJQUFJLENBQUMsYUFBYSwyQkFBMkIsZ0JBQWdCLEVBQUUsQ0FBQztRQUN6RixDQUFDO2FBQU0sQ0FBQztZQUNOLDJEQUEyRDtZQUMzRCxpQkFBaUIsR0FBRyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUNyRCxDQUFDO1FBRUQsOEVBQThFO1FBQzlFLElBQUksUUFBc0MsQ0FBQztRQUUzQyxJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksT0FBUSxJQUFJLENBQUMsUUFBZ0IsQ0FBQyxhQUFhLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDL0UseUNBQXlDO1lBQ3pDLFFBQVEsR0FBRyxNQUFPLElBQUksQ0FBQyxRQUFnQixDQUFDLGFBQWEsQ0FBQztnQkFDcEQsYUFBYSxFQUFFLGlCQUFpQjtnQkFDaEMsV0FBVyxFQUFFLFdBQVc7Z0JBQ3hCLGNBQWMsRUFBRSxFQUFFO2dCQUNsQixNQUFNLEVBQUUsTUFBTTtnQkFDZCxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87YUFDdEIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQzthQUFNLENBQUM7WUFDTixpQ0FBaUM7WUFDakMsUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7Z0JBQ2xDLGFBQWEsRUFBRSxpQkFBaUI7Z0JBQ2hDLFdBQVcsRUFBRSxXQUFXO2dCQUN4QixjQUFjLEVBQUUsRUFBRTtnQkFDbEIsTUFBTSxFQUFFLE1BQU07YUFDZixDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsK0ZBQStGO1FBQy9GLE1BQU0sY0FBYyxHQUFnQztZQUNsRCxJQUFJLEVBQUUsV0FBVztZQUNqQixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87WUFDekIsU0FBUyxFQUFFLFFBQVEsQ0FBQyxTQUFTO1NBQzlCLENBQUM7UUFDRixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUV6QyxPQUFPO1lBQ0wsSUFBSSxFQUFFLFdBQVc7WUFDakIsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPO1NBQzFCLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsbUJBQW1CLENBQUMsT0FBZTtRQUM5QyxpQ0FBaUM7UUFDakMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUM7WUFDdkIsSUFBSSxFQUFFLE1BQU07WUFDWixPQUFPLEVBQUUsT0FBTztTQUNqQixDQUFDLENBQUM7UUFFSCw0REFBNEQ7UUFDNUQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQ3JDLElBQUksaUJBQXlCLENBQUM7UUFDOUIsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDdEQsaUJBQWlCLEdBQUcsR0FBRyxJQUFJLENBQUMsYUFBYSwyQkFBMkIsZ0JBQWdCLEVBQUUsQ0FBQztRQUN6RixDQUFDO2FBQU0sQ0FBQztZQUNOLGlCQUFpQixHQUFHLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1FBQ3JELENBQUM7UUFFRCxvREFBb0Q7UUFDcEQsdUVBQXVFO1FBQ3ZFLElBQUksY0FBNkMsQ0FBQztRQUNsRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLGlDQUFpQztRQUV2RixJQUFJLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLElBQUksV0FBVyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUNoRixrRUFBa0U7WUFDbEUsY0FBYyxHQUFHO2dCQUNmLFdBQVcsQ0FBQyxDQUFDLENBQUMsRUFBRSxnQkFBZ0I7Z0JBQ2hDLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsa0JBQWtCO2FBQ3pFLENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLGNBQWMsR0FBRyxXQUFXLENBQUM7UUFDL0IsQ0FBQztRQUVELDhFQUE4RTtRQUM5RSxJQUFJLFFBQXNDLENBQUM7UUFFM0MsSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLE9BQVEsSUFBSSxDQUFDLFFBQWdCLENBQUMsYUFBYSxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQy9FLHlDQUF5QztZQUN6QyxRQUFRLEdBQUcsTUFBTyxJQUFJLENBQUMsUUFBZ0IsQ0FBQyxhQUFhLENBQUM7Z0JBQ3BELGFBQWEsRUFBRSxpQkFBaUI7Z0JBQ2hDLFdBQVcsRUFBRSxPQUFPO2dCQUNwQixjQUFjLEVBQUUsY0FBYztnQkFDOUIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO2FBQ3RCLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ04saUNBQWlDO1lBQ2pDLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO2dCQUNsQyxhQUFhLEVBQUUsaUJBQWlCO2dCQUNoQyxXQUFXLEVBQUUsT0FBTztnQkFDcEIsY0FBYyxFQUFFLGNBQWM7YUFDL0IsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELHFFQUFxRTtRQUNyRSxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQztZQUN2QixJQUFJLEVBQUUsV0FBVztZQUNqQixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87WUFDekIsU0FBUyxFQUFFLFFBQVEsQ0FBQyxTQUFTO1NBQzlCLENBQUMsQ0FBQztRQUVILE9BQU87WUFDTCxJQUFJLEVBQUUsV0FBVztZQUNqQixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87U0FDMUIsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNJLHNCQUFzQixDQUFDLFFBQWdCO1FBQzVDLE1BQU0sU0FBUyxHQUFtQyxFQUFFLENBQUM7UUFFckQsMENBQTBDO1FBQzFDLE1BQU0sYUFBYSxHQUFHLHFDQUFxQyxDQUFDO1FBQzVELElBQUksS0FBSyxDQUFDO1FBRVYsT0FBTyxDQUFDLEtBQUssR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDdkQsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRXpCLElBQUksQ0FBQztnQkFDSCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ3BELElBQUksUUFBUSxFQUFFLENBQUM7b0JBQ2IsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDM0IsQ0FBQztZQUNILENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLDRCQUE0QjtnQkFDNUIsT0FBTyxDQUFDLElBQUksQ0FBQyw0QkFBNEIsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNwRCxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRDs7T0FFRztJQUNLLG9CQUFvQixDQUFDLE9BQWU7UUFDMUMsb0JBQW9CO1FBQ3BCLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUN4RCxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQzVCLE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUVyQyxpQkFBaUI7UUFDakIsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxXQUFXO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDOUIsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRXJDLHdCQUF3QjtRQUN4QixNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLDhCQUE4QixDQUFDLENBQUM7UUFDbEUsSUFBSSxNQUFNLEdBQTRCLEVBQUUsQ0FBQztRQUN6QyxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2hCLElBQUksQ0FBQztnQkFDSCxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUM3QyxDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLHFEQUFxRDtnQkFDckQsTUFBTSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNyRCxDQUFDO1FBQ0gsQ0FBQztRQUVELCtCQUErQjtRQUMvQixNQUFNLGNBQWMsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7UUFDM0UsTUFBTSxTQUFTLEdBQUcsY0FBYyxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUV4RSxPQUFPO1lBQ0wsVUFBVSxFQUFFLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtZQUNyQyxRQUFRO1lBQ1IsTUFBTTtZQUNOLE1BQU07WUFDTixTQUFTO1NBQ1YsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNLLG9CQUFvQixDQUFDLE9BQWU7UUFDMUMsTUFBTSxNQUFNLEdBQTRCLEVBQUUsQ0FBQztRQUMzQyxNQUFNLFVBQVUsR0FBRywwQkFBMEIsQ0FBQztRQUM5QyxJQUFJLEtBQUssQ0FBQztRQUVWLE9BQU8sQ0FBQyxLQUFLLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1lBQ25ELE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNyQixJQUFJLEtBQUssR0FBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7WUFFckMsMENBQTBDO1lBQzFDLElBQUksQ0FBQztnQkFDSCxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFlLENBQUMsQ0FBQztZQUN0QyxDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLG1DQUFtQztZQUNyQyxDQUFDO1lBRUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQztRQUN0QixDQUFDO1FBRUQsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksY0FBYyxDQUFDLFFBQWdCO1FBQ3BDLHdDQUF3QztRQUN4QyxNQUFNLGlCQUFpQixHQUFHO1lBQ3hCLGlCQUFpQjtZQUNqQixrQkFBa0I7WUFDbEIsZUFBZTtZQUNmLDZCQUE2QjtTQUM5QixDQUFDO1FBRUYsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzdDLE9BQU8saUJBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQ3JDLGFBQWEsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQzdDLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSxrQkFBa0IsQ0FBQyxRQUFnQjtRQUN4QyxNQUFNLG9CQUFvQixHQUFHO1lBQzNCLHVCQUF1QjtZQUN2QixZQUFZO1lBQ1osZ0JBQWdCO1lBQ2hCLG1CQUFtQjtZQUNuQixxQkFBcUI7U0FDdEIsQ0FBQztRQUVGLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM3QyxPQUFPLG9CQUFvQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUN4QyxhQUFhLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUM3QyxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ksaUJBQWlCLENBQUMsUUFBZ0I7UUFDdkMsa0NBQWtDO1FBQ2xDLE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQztRQUM3RSxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2hCLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQy9CLENBQUM7UUFFRCxNQUFNLGFBQWEsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLDRDQUE0QyxDQUFDLENBQUM7UUFDbkYsSUFBSSxhQUFhLEVBQUUsQ0FBQztZQUNsQixPQUFPLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNqQyxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxxQkFBcUI7UUFDM0IsTUFBTSxZQUFZLEdBQWEsRUFBRSxDQUFDO1FBRWxDLEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQ3ZDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUMsQ0FBQztRQUMvQyxDQUFDO1FBRUQsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRDs7T0FFRztJQUNLLGtCQUFrQjtRQUN4QixPQUFPLFFBQVEsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzVFLENBQUM7SUFFRDs7T0FFRztJQUNLLHVCQUF1QjtRQUM3QixPQUFPOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztnR0FnQ3FGLENBQUM7SUFDL0YsQ0FBQztJQUVEOzs7T0FHRztJQUNLLHVCQUF1QjtRQUM3Qix3RUFBd0U7UUFDeEUsSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssSUFBSSxDQUFDLHVCQUF1QixFQUFFLEVBQUUsQ0FBQztZQUNoRixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUM7UUFDNUIsQ0FBQztRQUVELE9BQU87Ozs7Ozs7Ozs7Ozs7Ozs7aUdBZ0JzRixDQUFDO0lBQ2hHLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUs7UUFDVixJQUFJLENBQUMsY0FBYyxHQUFHLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsbUNBQW1DO0lBQ25DLDhCQUE4QjtJQUM5QixtQ0FBbUM7SUFFbkM7Ozs7OztPQU1HO0lBQ0ksS0FBSyxDQUFDLHdCQUF3QixDQUNuQyxJQUFZLEVBQ1osTUFBaUI7UUFFakIsd0JBQXdCO1FBQ3hCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBRXpCLGlGQUFpRjtRQUNqRixNQUFNLFdBQVcsR0FBRyxTQUFTLElBQUkseUZBQXlGLENBQUM7UUFFM0gsaUJBQWlCO1FBQ2pCLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDO1lBQ3ZCLElBQUksRUFBRSxNQUFNO1lBQ1osT0FBTyxFQUFFLFdBQVc7U0FDckIsQ0FBQyxDQUFDO1FBRUgsK0NBQStDO1FBQy9DLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLDJCQUEyQixFQUFFLENBQUM7UUFFN0Qsa0NBQWtDO1FBQ2xDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBRTFDLDBEQUEwRDtRQUMxRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBZSxDQUFDO1FBQ3RDLElBQUksT0FBTyxRQUFRLENBQUMscUJBQXFCLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDekQsTUFBTSxJQUFJLEtBQUssQ0FBQyx5RUFBeUUsQ0FBQyxDQUFDO1FBQzdGLENBQUM7UUFFRCw2REFBNkQ7UUFDN0QsTUFBTSxRQUFRLEdBQUcsTUFBTSxRQUFRLENBQUMscUJBQXFCLENBQ25EO1lBQ0UsYUFBYSxFQUFFLGlCQUFpQjtZQUNoQyxXQUFXLEVBQUUsV0FBVztZQUN4QixjQUFjLEVBQUUsRUFBRTtZQUNsQixNQUFNLEVBQUUsTUFBTTtZQUNkLEtBQUssRUFBRSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTO1NBQzVDO1FBQ0QsNEVBQTRFO1FBQzVFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBVSxFQUFFLEVBQUU7WUFDNUIsSUFBSSxLQUFLLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDbkMsd0RBQXdEO2dCQUN4RCxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7b0JBQzNCLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUM7b0JBQzlCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7Z0JBQy9CLENBQUM7Z0JBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDL0IsQ0FBQztZQUNELElBQUksS0FBSyxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2xDLHFEQUFxRDtnQkFDckQsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztvQkFDMUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztvQkFDNUIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQztnQkFDaEMsQ0FBQztnQkFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM5QixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQ2QsQ0FBQztRQUVGLGdEQUFnRDtRQUNoRCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO1FBRTlCLG9DQUFvQztRQUNwQyxNQUFNLGNBQWMsR0FBUTtZQUMxQixJQUFJLEVBQUUsV0FBVztZQUNqQixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU8sSUFBSSxFQUFFO1lBQy9CLFNBQVMsRUFBRSxRQUFRLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxTQUFTO1NBQ25ELENBQUM7UUFFRixtRUFBbUU7UUFDbkUsa0ZBQWtGO1FBQ2xGLElBQUksUUFBUSxDQUFDLFNBQVMsSUFBSSxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN4RCxjQUFjLENBQUMsVUFBVSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUMvRCxRQUFRLEVBQUU7b0JBQ1IsSUFBSSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSTtvQkFDdEIsU0FBUyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsU0FBUztpQkFDakM7YUFDRixDQUFDLENBQUMsQ0FBQztRQUNOLENBQUM7UUFFRCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxjQUF3RCxDQUFDLENBQUM7UUFFbkYsMENBQTBDO1FBQzFDLElBQUksU0FBbUQsQ0FBQztRQUN4RCxJQUFJLFFBQVEsQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDeEQsU0FBUyxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUMvQyxRQUFRLEVBQUU7b0JBQ1IsSUFBSSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSTtvQkFDdEIsU0FBUyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsU0FBUztvQkFDaEMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsS0FBSztpQkFDekI7YUFDRixDQUFDLENBQUMsQ0FBQztRQUNOLENBQUM7UUFFRCxPQUFPO1lBQ0wsT0FBTyxFQUFFO2dCQUNQLElBQUksRUFBRSxXQUFXO2dCQUNqQixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU8sSUFBSSxFQUFFO2FBQ2hDO1lBQ0QsU0FBUztTQUNWLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsdUJBQXVCLENBQ2xDLE9BQWUsRUFDZixRQUFpQjtRQUVqQixpQ0FBaUM7UUFDakMsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLDhEQUE4RDtZQUM5RCw0RUFBNEU7WUFDNUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUM7Z0JBQ3ZCLElBQUksRUFBRSxNQUFNO2dCQUNaLE9BQU8sRUFBRSxPQUFPO2dCQUNoQixRQUFRLEVBQUUsUUFBUTthQUN1QixDQUFDLENBQUM7UUFDL0MsQ0FBQzthQUFNLENBQUM7WUFDTix1QkFBdUI7WUFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUM7Z0JBQ3ZCLElBQUksRUFBRSxNQUFNO2dCQUNaLE9BQU8sRUFBRSxPQUFPO2FBQ2pCLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCx1QkFBdUI7UUFDdkIsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztRQUU3RCxrQ0FBa0M7UUFDbEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFFMUMsb0RBQW9EO1FBQ3BELGlFQUFpRTtRQUNqRSwrRUFBK0U7UUFDL0UsSUFBSSxjQUE2QyxDQUFDO1FBQ2xELE1BQU0sV0FBVyxHQUFHLFFBQVE7WUFDMUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUUsaUNBQWlDO1lBQ3hELENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFFLDRCQUE0QjtRQUVuRSxJQUFJLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLElBQUksV0FBVyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUNoRixjQUFjLEdBQUc7Z0JBQ2YsV0FBVyxDQUFDLENBQUMsQ0FBQztnQkFDZCxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLENBQUMsQ0FBQzthQUNyRCxDQUFDO1FBQ0osQ0FBQzthQUFNLENBQUM7WUFDTixjQUFjLEdBQUcsV0FBVyxDQUFDO1FBQy9CLENBQUM7UUFFRCxpREFBaUQ7UUFDakQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQWUsQ0FBQztRQUN0QyxJQUFJLE9BQU8sUUFBUSxDQUFDLHFCQUFxQixLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQ3pELE1BQU0sSUFBSSxLQUFLLENBQUMsbUZBQW1GLENBQUMsQ0FBQztRQUN2RyxDQUFDO1FBRUQsOEVBQThFO1FBQzlFLE1BQU0sV0FBVyxHQUFHLFFBQVE7WUFDMUIsQ0FBQyxDQUFDLGtFQUFrRTtZQUNwRSxDQUFDLENBQUMsT0FBTyxDQUFDO1FBRVosNkRBQTZEO1FBQzdELE1BQU0sUUFBUSxHQUFHLE1BQU0sUUFBUSxDQUFDLHFCQUFxQixDQUNuRDtZQUNFLGFBQWEsRUFBRSxpQkFBaUI7WUFDaEMsV0FBVyxFQUFFLFdBQVc7WUFDeEIsY0FBYyxFQUFFLGNBQWM7WUFDOUIsS0FBSyxFQUFFLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVM7U0FDNUM7UUFDRCw0RUFBNEU7UUFDNUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFVLEVBQUUsRUFBRTtZQUM1QixJQUFJLEtBQUssQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNuQyx3REFBd0Q7Z0JBQ3hELElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztvQkFDM0IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztvQkFDOUIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztnQkFDL0IsQ0FBQztnQkFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMvQixDQUFDO1lBQ0QsSUFBSSxLQUFLLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDbEMscURBQXFEO2dCQUNyRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO29CQUMxQixJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDO29CQUM1QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO2dCQUNoQyxDQUFDO2dCQUNELElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzlCLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FDZCxDQUFDO1FBRUYsZ0RBQWdEO1FBQ2hELElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7UUFFOUIsb0NBQW9DO1FBQ3BDLE1BQU0sY0FBYyxHQUFRO1lBQzFCLElBQUksRUFBRSxXQUFXO1lBQ2pCLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTyxJQUFJLEVBQUU7WUFDL0IsU0FBUyxFQUFFLFFBQVEsQ0FBQyxRQUFRLElBQUksUUFBUSxDQUFDLFNBQVM7U0FDbkQsQ0FBQztRQUVGLG1FQUFtRTtRQUNuRSxrRkFBa0Y7UUFDbEYsSUFBSSxRQUFRLENBQUMsU0FBUyxJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3hELGNBQWMsQ0FBQyxVQUFVLEdBQUcsUUFBUSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQy9ELFFBQVEsRUFBRTtvQkFDUixJQUFJLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJO29CQUN0QixTQUFTLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxTQUFTO2lCQUNqQzthQUNGLENBQUMsQ0FBQyxDQUFDO1FBQ04sQ0FBQztRQUVELElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLGNBQXdELENBQUMsQ0FBQztRQUVuRiwwQ0FBMEM7UUFDMUMsSUFBSSxTQUFtRCxDQUFDO1FBQ3hELElBQUksUUFBUSxDQUFDLFNBQVMsSUFBSSxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN4RCxTQUFTLEdBQUcsUUFBUSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQy9DLFFBQVEsRUFBRTtvQkFDUixJQUFJLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJO29CQUN0QixTQUFTLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxTQUFTO29CQUNoQyxLQUFLLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxLQUFLO2lCQUN6QjthQUNGLENBQUMsQ0FBQyxDQUFDO1FBQ04sQ0FBQztRQUVELE9BQU87WUFDTCxPQUFPLEVBQUU7Z0JBQ1AsSUFBSSxFQUFFLFdBQVc7Z0JBQ2pCLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTyxJQUFJLEVBQUU7YUFDaEM7WUFDRCxTQUFTO1NBQ1YsQ0FBQztJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSywyQkFBMkI7UUFDakMsT0FBTzs7Ozs7Ozs7Ozs7Ozs7MkRBY2dELENBQUM7SUFDMUQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxvQkFBb0I7UUFDekIsTUFBTSxLQUFLLEdBQWtDLEVBQUUsQ0FBQztRQUVoRCxLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUN2QyxLQUFLLE1BQU0sTUFBTSxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDbEMsNkNBQTZDO2dCQUM3QyxNQUFNLE9BQU8sR0FBZ0M7b0JBQzNDLElBQUksRUFBRSxVQUFVO29CQUNoQixRQUFRLEVBQUU7d0JBQ1IsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUcsd0JBQXdCO3dCQUM5RCxXQUFXLEVBQUUsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxXQUFXLEVBQUU7d0JBQ25ELFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBbUU7cUJBQ3ZGO2lCQUNGLENBQUM7Z0JBQ0YsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN0QixDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxvQkFBb0IsQ0FDekIsU0FBdUM7UUFFdkMsT0FBTyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQ3hCLDhEQUE4RDtZQUM5RCxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztZQUNsQyxNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBRTlDLElBQUksUUFBZ0IsQ0FBQztZQUNyQixJQUFJLE1BQWMsQ0FBQztZQUVuQixJQUFJLGVBQWUsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDeEIsUUFBUSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLGVBQWUsQ0FBQyxDQUFDO2dCQUNsRCxNQUFNLEdBQUcsUUFBUSxDQUFDLFNBQVMsQ0FBQyxlQUFlLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDbkQsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLDZEQUE2RDtnQkFDN0QsUUFBUSxHQUFHLFFBQVEsQ0FBQztnQkFDcEIsTUFBTSxHQUFHLEVBQUUsQ0FBQztZQUNkLENBQUM7WUFFRCxPQUFPO2dCQUNMLFVBQVUsRUFBRSxJQUFJLENBQUMsa0JBQWtCLEVBQUU7Z0JBQ3JDLFFBQVE7Z0JBQ1IsTUFBTTtnQkFDTixNQUFNLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxTQUFTO2FBQzlCLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRiJ9