mcp-perplexity-pro 1.1.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 (96) hide show
  1. package/README.md +638 -0
  2. package/bin/mcp-perplexity-pro +8 -0
  3. package/bin/mcp-perplexity-pro-stdio +9 -0
  4. package/dist/claude-code-bridge.d.ts +3 -0
  5. package/dist/claude-code-bridge.d.ts.map +1 -0
  6. package/dist/claude-code-bridge.js +111 -0
  7. package/dist/claude-code-bridge.js.map +1 -0
  8. package/dist/http-index.d.ts +3 -0
  9. package/dist/http-index.d.ts.map +1 -0
  10. package/dist/http-index.js +38 -0
  11. package/dist/http-index.js.map +1 -0
  12. package/dist/http-server.d.ts +33 -0
  13. package/dist/http-server.d.ts.map +1 -0
  14. package/dist/http-server.js +362 -0
  15. package/dist/http-server.js.map +1 -0
  16. package/dist/http-streaming-server.d.ts +4 -0
  17. package/dist/http-streaming-server.d.ts.map +1 -0
  18. package/dist/http-streaming-server.js +514 -0
  19. package/dist/http-streaming-server.js.map +1 -0
  20. package/dist/index.d.ts +3 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +43 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/launcher.d.ts +3 -0
  25. package/dist/launcher.d.ts.map +1 -0
  26. package/dist/launcher.js +209 -0
  27. package/dist/launcher.js.map +1 -0
  28. package/dist/mcp-server.d.ts +5 -0
  29. package/dist/mcp-server.d.ts.map +1 -0
  30. package/dist/mcp-server.js +329 -0
  31. package/dist/mcp-server.js.map +1 -0
  32. package/dist/models.d.ts +45 -0
  33. package/dist/models.d.ts.map +1 -0
  34. package/dist/models.js +284 -0
  35. package/dist/models.js.map +1 -0
  36. package/dist/perplexity-api.d.ts +59 -0
  37. package/dist/perplexity-api.d.ts.map +1 -0
  38. package/dist/perplexity-api.js +455 -0
  39. package/dist/perplexity-api.js.map +1 -0
  40. package/dist/port-utils.d.ts +31 -0
  41. package/dist/port-utils.d.ts.map +1 -0
  42. package/dist/port-utils.js +114 -0
  43. package/dist/port-utils.js.map +1 -0
  44. package/dist/project-manager.d.ts +91 -0
  45. package/dist/project-manager.d.ts.map +1 -0
  46. package/dist/project-manager.js +422 -0
  47. package/dist/project-manager.js.map +1 -0
  48. package/dist/simple-streaming.d.ts +26 -0
  49. package/dist/simple-streaming.d.ts.map +1 -0
  50. package/dist/simple-streaming.js +75 -0
  51. package/dist/simple-streaming.js.map +1 -0
  52. package/dist/sse-index.d.ts +3 -0
  53. package/dist/sse-index.d.ts.map +1 -0
  54. package/dist/sse-index.js +38 -0
  55. package/dist/sse-index.js.map +1 -0
  56. package/dist/sse-server.d.ts +4 -0
  57. package/dist/sse-server.d.ts.map +1 -0
  58. package/dist/sse-server.js +208 -0
  59. package/dist/sse-server.js.map +1 -0
  60. package/dist/stdio-bridge.d.ts +21 -0
  61. package/dist/stdio-bridge.d.ts.map +1 -0
  62. package/dist/stdio-bridge.js +157 -0
  63. package/dist/stdio-bridge.js.map +1 -0
  64. package/dist/stdio-server.d.ts +7 -0
  65. package/dist/stdio-server.d.ts.map +1 -0
  66. package/dist/stdio-server.js +396 -0
  67. package/dist/stdio-server.js.map +1 -0
  68. package/dist/storage.d.ts +65 -0
  69. package/dist/storage.d.ts.map +1 -0
  70. package/dist/storage.js +328 -0
  71. package/dist/storage.js.map +1 -0
  72. package/dist/streaming-wrapper.d.ts +63 -0
  73. package/dist/streaming-wrapper.d.ts.map +1 -0
  74. package/dist/streaming-wrapper.js +452 -0
  75. package/dist/streaming-wrapper.js.map +1 -0
  76. package/dist/tools/async.d.ts +28 -0
  77. package/dist/tools/async.d.ts.map +1 -0
  78. package/dist/tools/async.js +167 -0
  79. package/dist/tools/async.js.map +1 -0
  80. package/dist/tools/chat.d.ts +29 -0
  81. package/dist/tools/chat.d.ts.map +1 -0
  82. package/dist/tools/chat.js +233 -0
  83. package/dist/tools/chat.js.map +1 -0
  84. package/dist/tools/projects.d.ts +19 -0
  85. package/dist/tools/projects.d.ts.map +1 -0
  86. package/dist/tools/projects.js +219 -0
  87. package/dist/tools/projects.js.map +1 -0
  88. package/dist/tools/query.d.ts +13 -0
  89. package/dist/tools/query.d.ts.map +1 -0
  90. package/dist/tools/query.js +178 -0
  91. package/dist/tools/query.js.map +1 -0
  92. package/dist/types.d.ts +330 -0
  93. package/dist/types.d.ts.map +1 -0
  94. package/dist/types.js +90 -0
  95. package/dist/types.js.map +1 -0
  96. package/package.json +89 -0
@@ -0,0 +1,452 @@
1
+ import { PerplexityApiClient } from './perplexity-api.js';
2
+ import { selectOptimalModel } from './models.js';
3
+ /**
4
+ * Active streaming operations registry
5
+ */
6
+ const activeStreams = new Map();
7
+ /**
8
+ * Universal async tool wrapper that creates async jobs and streams progress to Claude Code
9
+ */
10
+ export class StreamingWrapper {
11
+ server;
12
+ config;
13
+ constructor(server, config) {
14
+ this.server = server;
15
+ this.config = config;
16
+ }
17
+ /**
18
+ * Execute a tool call with streaming content updates (not just progress)
19
+ */
20
+ async executeWithStreaming(toolName, params, progressToken) {
21
+ // If no progress token provided, execute synchronously (backwards compatibility)
22
+ if (!progressToken) {
23
+ return this.executeSynchronously(toolName, params);
24
+ }
25
+ try {
26
+ // Create async job based on tool type
27
+ const asyncJob = await this.createAsyncJob(toolName, params);
28
+ if ('error' in asyncJob) {
29
+ return asyncJob;
30
+ }
31
+ // Register streaming state
32
+ const streamState = {
33
+ jobId: asyncJob.id,
34
+ progressToken,
35
+ server: this.server,
36
+ startTime: Date.now(),
37
+ lastProgress: 0,
38
+ toolName,
39
+ params,
40
+ config: this.config,
41
+ };
42
+ activeStreams.set(asyncJob.id, streamState);
43
+ // Start streaming content (not just progress)
44
+ this.startContentStreaming(asyncJob.id);
45
+ // Return initial response indicating streaming has started
46
+ return {
47
+ content: [
48
+ {
49
+ type: 'text',
50
+ text: `🚀 Starting ${toolName}...\n\n`,
51
+ },
52
+ ],
53
+ };
54
+ }
55
+ catch (error) {
56
+ return {
57
+ content: [
58
+ {
59
+ type: 'text',
60
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
61
+ },
62
+ ],
63
+ isError: true,
64
+ };
65
+ }
66
+ }
67
+ /**
68
+ * Create async job based on tool type
69
+ */
70
+ async createAsyncJob(toolName, params) {
71
+ const apiClient = new PerplexityApiClient(this.config);
72
+ // Determine the query/content based on tool type
73
+ let query;
74
+ let model;
75
+ switch (toolName) {
76
+ case 'ask_perplexity':
77
+ query = params.query;
78
+ model = params.model || selectOptimalModel(query, undefined, this.config.default_model);
79
+ break;
80
+ case 'chat_perplexity':
81
+ query = params.message;
82
+ model = params.model || selectOptimalModel(query, undefined, this.config.default_model);
83
+ break;
84
+ case 'research_perplexity':
85
+ query = params.topic;
86
+ model = params.model || 'sonar-deep-research';
87
+ break;
88
+ default:
89
+ throw new Error(`Unsupported tool for streaming: ${toolName}`);
90
+ }
91
+ // Create the async request
92
+ const request = {
93
+ model,
94
+ messages: [{ role: 'user', content: query }],
95
+ temperature: params.temperature ?? 0.2,
96
+ ...(params.max_tokens && { max_tokens: params.max_tokens }),
97
+ ...(params.search_domain_filter && { search_domain_filter: params.search_domain_filter }),
98
+ ...(params.return_images && { return_images: params.return_images }),
99
+ ...(params.return_related_questions && {
100
+ return_related_questions: params.return_related_questions,
101
+ }),
102
+ };
103
+ return await apiClient.createAsyncChatCompletion(request);
104
+ }
105
+ /**
106
+ * Execute tool synchronously (fallback for no progress token)
107
+ */
108
+ async executeSynchronously(toolName, params) {
109
+ // Import handlers dynamically to avoid circular dependencies
110
+ const { handleAskPerplexity, handleResearchPerplexity } = await import('./tools/query.js');
111
+ const { handleChatPerplexity } = await import('./tools/chat.js');
112
+ switch (toolName) {
113
+ case 'ask_perplexity':
114
+ return await handleAskPerplexity(params, this.config);
115
+ case 'chat_perplexity': {
116
+ const result = await handleChatPerplexity(params, this.config);
117
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
118
+ }
119
+ case 'research_perplexity': {
120
+ const researchResult = await handleResearchPerplexity(params, this.config);
121
+ return { content: [{ type: 'text', text: JSON.stringify(researchResult, null, 2) }] };
122
+ }
123
+ default:
124
+ throw new Error(`Unknown tool: ${toolName}`);
125
+ }
126
+ }
127
+ /**
128
+ * Start streaming actual content from async job (not just progress)
129
+ */
130
+ async startContentStreaming(jobId) {
131
+ const state = activeStreams.get(jobId);
132
+ if (!state)
133
+ return;
134
+ const apiClient = new PerplexityApiClient(this.config);
135
+ let pollCount = 0;
136
+ let lastContentLength = 0;
137
+ const maxPolls = 60; // 5 minutes max (5s intervals)
138
+ const pollAndStreamContent = async () => {
139
+ try {
140
+ const jobStatus = await apiClient.getAsyncJob(jobId);
141
+ if (!activeStreams.has(jobId)) {
142
+ // Stream was cancelled
143
+ return;
144
+ }
145
+ pollCount++;
146
+ // Check if we have new content to stream
147
+ const currentContent = jobStatus.choices?.[0]?.message?.content || '';
148
+ if (currentContent.length > lastContentLength) {
149
+ // We have new content! Stream the delta
150
+ const newContent = currentContent.slice(lastContentLength);
151
+ await this.streamContentChunk(state, newContent, jobStatus.status);
152
+ lastContentLength = currentContent.length;
153
+ }
154
+ // Send status updates for major state changes
155
+ if (jobStatus.status === 'STARTED' && state.lastProgress < 25) {
156
+ await this.streamContentChunk(state, '📡 Processing your request...\n\n', jobStatus.status);
157
+ state.lastProgress = 25;
158
+ }
159
+ // Handle completion
160
+ if (jobStatus.status === 'COMPLETED') {
161
+ // Stream any remaining content
162
+ if (currentContent.length > lastContentLength) {
163
+ const finalContent = currentContent.slice(lastContentLength);
164
+ await this.streamContentChunk(state, finalContent, jobStatus.status);
165
+ }
166
+ // Process final job result (save report, etc.)
167
+ await this.handleJobCompletion(jobId, jobStatus);
168
+ // Stream completion message
169
+ await this.streamContentChunk(state, '\n\n✅ Complete!', 'COMPLETED');
170
+ activeStreams.delete(jobId);
171
+ return;
172
+ }
173
+ else if (jobStatus.status === 'FAILED') {
174
+ await this.streamContentChunk(state, `\n\n❌ Job failed: ${jobStatus.error || 'Unknown error'}`, 'FAILED');
175
+ activeStreams.delete(jobId);
176
+ return;
177
+ }
178
+ // Continue polling if job is still running
179
+ if (pollCount < maxPolls &&
180
+ (jobStatus.status === 'CREATED' || jobStatus.status === 'STARTED')) {
181
+ setTimeout(pollAndStreamContent, 2000); // Poll every 2 seconds for more responsive streaming
182
+ }
183
+ else if (pollCount >= maxPolls) {
184
+ // Timeout reached
185
+ await this.streamContentChunk(state, '\n\n⏰ Request timed out after 5 minutes', 'FAILED');
186
+ activeStreams.delete(jobId);
187
+ }
188
+ }
189
+ catch (error) {
190
+ console.error(`Error polling job ${jobId}:`, error);
191
+ await this.streamContentChunk(state, `\n\n❌ Error: ${error instanceof Error ? error.message : String(error)}`, 'FAILED');
192
+ activeStreams.delete(jobId);
193
+ }
194
+ };
195
+ // Start polling immediately
196
+ setTimeout(pollAndStreamContent, 500); // Start after 500ms
197
+ }
198
+ /**
199
+ * Stream a chunk of content to Claude Code
200
+ */
201
+ async streamContentChunk(state, content, status) {
202
+ try {
203
+ // Use MCP's streaming capabilities to send partial content
204
+ // This creates the illusion of real-time streaming by sending content in chunks
205
+ await state.server.notification({
206
+ method: 'notifications/message',
207
+ params: {
208
+ level: 'info',
209
+ logger: `mcp-perplexity-${state.toolName}`,
210
+ data: {
211
+ type: 'content_chunk',
212
+ content: content,
213
+ job_id: state.jobId,
214
+ status: status,
215
+ timestamp: Date.now(),
216
+ },
217
+ },
218
+ });
219
+ // Also send to stdout for CLI clients that capture output
220
+ process.stdout.write(content);
221
+ }
222
+ catch (error) {
223
+ console.error('Error streaming content chunk:', error);
224
+ }
225
+ }
226
+ /**
227
+ * Legacy method - keeping for backwards compatibility
228
+ */
229
+ async startProgressStreaming(jobId) {
230
+ const state = activeStreams.get(jobId);
231
+ if (!state)
232
+ return;
233
+ const apiClient = new PerplexityApiClient(this.config);
234
+ let pollCount = 0;
235
+ const maxPolls = 60; // 5 minutes max (5s intervals)
236
+ const pollProgress = async () => {
237
+ try {
238
+ const jobStatus = await apiClient.getAsyncJob(jobId);
239
+ if (!activeStreams.has(jobId)) {
240
+ // Stream was cancelled
241
+ return;
242
+ }
243
+ pollCount++;
244
+ // Calculate progress based on status and elapsed time
245
+ let progress = state.lastProgress;
246
+ let total = 100;
247
+ switch (jobStatus.status) {
248
+ case 'CREATED':
249
+ progress = Math.min(10 + pollCount * 2, 20);
250
+ break;
251
+ case 'STARTED':
252
+ progress = Math.min(25 + pollCount * 3, 80);
253
+ break;
254
+ case 'COMPLETED':
255
+ progress = 100;
256
+ break;
257
+ case 'FAILED':
258
+ progress = 0;
259
+ total = 0;
260
+ break;
261
+ }
262
+ // Only send progress update if progress increased
263
+ if (progress > state.lastProgress ||
264
+ jobStatus.status === 'COMPLETED' ||
265
+ jobStatus.status === 'FAILED') {
266
+ await this.sendProgressNotification(state, progress, total, jobStatus);
267
+ state.lastProgress = progress;
268
+ }
269
+ // Handle completion or failure
270
+ if (jobStatus.status === 'COMPLETED') {
271
+ await this.handleJobCompletion(jobId, jobStatus);
272
+ activeStreams.delete(jobId);
273
+ return;
274
+ }
275
+ else if (jobStatus.status === 'FAILED') {
276
+ await this.handleJobFailure(jobId, jobStatus);
277
+ activeStreams.delete(jobId);
278
+ return;
279
+ }
280
+ // Continue polling if job is still running and we haven't exceeded max polls
281
+ if (pollCount < maxPolls &&
282
+ (jobStatus.status === 'CREATED' || jobStatus.status === 'STARTED')) {
283
+ setTimeout(pollProgress, 5000); // Poll every 5 seconds
284
+ }
285
+ else if (pollCount >= maxPolls) {
286
+ // Timeout reached
287
+ await this.sendProgressNotification(state, 0, 0, {
288
+ ...jobStatus,
289
+ status: 'FAILED',
290
+ error: 'Job timed out after 5 minutes',
291
+ });
292
+ activeStreams.delete(jobId);
293
+ }
294
+ }
295
+ catch (error) {
296
+ console.error(`Error polling job ${jobId}:`, error);
297
+ // Send error notification
298
+ await this.sendProgressNotification(state, 0, 0, {
299
+ id: jobId,
300
+ status: 'FAILED',
301
+ error: error instanceof Error ? error.message : String(error),
302
+ created_at: Math.floor(Date.now() / 1000),
303
+ model: 'unknown',
304
+ });
305
+ activeStreams.delete(jobId);
306
+ }
307
+ };
308
+ // Start polling
309
+ setTimeout(pollProgress, 1000); // Start after 1 second
310
+ }
311
+ /**
312
+ * Send progress notification to Claude Code
313
+ */
314
+ async sendProgressNotification(state, progress, total, jobStatus) {
315
+ try {
316
+ const elapsedTime = Date.now() - state.startTime;
317
+ const statusMessage = this.getStatusMessage(jobStatus.status, progress, elapsedTime);
318
+ // Send MCP progress notification
319
+ await state.server.notification({
320
+ method: 'notifications/progress',
321
+ params: {
322
+ progressToken: state.progressToken,
323
+ progress,
324
+ total,
325
+ _meta: {
326
+ status: jobStatus.status,
327
+ job_id: jobStatus.id,
328
+ tool_name: state.toolName,
329
+ elapsed_time_ms: elapsedTime,
330
+ message: statusMessage,
331
+ ...(jobStatus.error && { error: jobStatus.error }),
332
+ },
333
+ },
334
+ });
335
+ }
336
+ catch (error) {
337
+ console.error('Error sending progress notification:', error);
338
+ }
339
+ }
340
+ /**
341
+ * Handle job completion and send final result
342
+ */
343
+ async handleJobCompletion(jobId, jobStatus) {
344
+ const state = activeStreams.get(jobId);
345
+ if (!state)
346
+ return;
347
+ try {
348
+ // Process the completed result based on tool type
349
+ const finalResult = await this.processCompletedJob(state.toolName, state.params, jobStatus);
350
+ // Send final progress notification with result
351
+ await state.server.notification({
352
+ method: 'notifications/progress',
353
+ params: {
354
+ progressToken: state.progressToken,
355
+ progress: 100,
356
+ total: 100,
357
+ _meta: {
358
+ status: 'COMPLETED',
359
+ job_id: jobId,
360
+ tool_name: state.toolName,
361
+ elapsed_time_ms: Date.now() - state.startTime,
362
+ message: 'Completed successfully',
363
+ final_result: finalResult,
364
+ },
365
+ },
366
+ });
367
+ }
368
+ catch (error) {
369
+ console.error(`Error handling job completion for ${jobId}:`, error);
370
+ }
371
+ }
372
+ /**
373
+ * Handle job failure
374
+ */
375
+ async handleJobFailure(jobId, jobStatus) {
376
+ const state = activeStreams.get(jobId);
377
+ if (!state)
378
+ return;
379
+ await this.sendProgressNotification(state, 0, 0, jobStatus);
380
+ }
381
+ /**
382
+ * Process completed job based on tool type
383
+ */
384
+ async processCompletedJob(toolName, params, jobStatus) {
385
+ // Save report if requested
386
+ if (params.save_report && jobStatus.choices?.[0]?.message?.content) {
387
+ const { StorageManager } = await import('./storage.js');
388
+ const { detectProjectWithSuggestions } = await import('./tools/projects.js');
389
+ const projectName = params.project_name || (await detectProjectWithSuggestions(undefined, this.config));
390
+ const toolSubdir = toolName.replace('_perplexity', '');
391
+ const projectConfig = {
392
+ ...this.config,
393
+ storage_path: `projects/${projectName}/${toolSubdir}`,
394
+ };
395
+ const storageManager = new StorageManager(projectConfig);
396
+ let reportContent;
397
+ switch (toolName) {
398
+ case 'ask_perplexity':
399
+ reportContent = `# Ask Perplexity Report\n\n**Query:** ${params.query}\n**Model:** ${jobStatus.model}\n**Timestamp:** ${new Date().toISOString()}\n\n## Response\n\n${jobStatus.choices[0].message.content}`;
400
+ break;
401
+ case 'research_perplexity':
402
+ reportContent = `# Research Report\n\n**Topic:** ${params.topic}\n**Model:** ${jobStatus.model}\n**Timestamp:** ${new Date().toISOString()}\n\n## Research Results\n\n${jobStatus.choices[0].message.content}`;
403
+ break;
404
+ case 'chat_perplexity':
405
+ reportContent = `# Chat Export\n\n**Message:** ${params.message}\n**Model:** ${jobStatus.model}\n**Timestamp:** ${new Date().toISOString()}\n\n## Response\n\n${jobStatus.choices[0].message.content}`;
406
+ break;
407
+ default:
408
+ reportContent = `# ${toolName} Report\n\n${jobStatus.choices[0].message.content}`;
409
+ }
410
+ await storageManager.saveReport(reportContent, `${toolName}-${Date.now()}`);
411
+ }
412
+ return {
413
+ job_id: jobStatus.id,
414
+ status: jobStatus.status,
415
+ model: jobStatus.model,
416
+ response: jobStatus.choices?.[0]?.message?.content || 'No response content',
417
+ usage: jobStatus.usage,
418
+ ...(params.save_report && { report_saved: true }),
419
+ };
420
+ }
421
+ /**
422
+ * Get status message for progress updates
423
+ */
424
+ getStatusMessage(status, progress, elapsedTime) {
425
+ const elapsedSeconds = Math.floor(elapsedTime / 1000);
426
+ switch (status) {
427
+ case 'CREATED':
428
+ return `Job created, waiting to start... (${elapsedSeconds}s)`;
429
+ case 'STARTED':
430
+ return `Processing... ${progress}% complete (${elapsedSeconds}s)`;
431
+ case 'COMPLETED':
432
+ return `Completed successfully! (${elapsedSeconds}s total)`;
433
+ case 'FAILED':
434
+ return `Job failed (${elapsedSeconds}s)`;
435
+ default:
436
+ return `Status: ${status} (${elapsedSeconds}s)`;
437
+ }
438
+ }
439
+ /**
440
+ * Cancel streaming for a job
441
+ */
442
+ cancelStreaming(jobId) {
443
+ activeStreams.delete(jobId);
444
+ }
445
+ /**
446
+ * Get active streaming jobs
447
+ */
448
+ getActiveStreams() {
449
+ return Array.from(activeStreams.keys());
450
+ }
451
+ }
452
+ //# sourceMappingURL=streaming-wrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-wrapper.js","sourceRoot":"","sources":["../src/streaming-wrapper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAiBjD;;GAEG;AACH,MAAM,aAAa,GAAG,IAAI,GAAG,EAA0B,CAAC;AAExD;;GAEG;AACH,MAAM,OAAO,gBAAgB;IACnB,MAAM,CAAS;IACf,MAAM,CAAS;IAEvB,YAAY,MAAc,EAAE,MAAc;QACxC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,oBAAoB,CACxB,QAAgB,EAChB,MAAW,EACX,aAA+B;QAE/B,iFAAiF;QACjF,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC;YACH,sCAAsC;YACtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAE7D,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;gBACxB,OAAO,QAAQ,CAAC;YAClB,CAAC;YAED,2BAA2B;YAC3B,MAAM,WAAW,GAAmB;gBAClC,KAAK,EAAE,QAAQ,CAAC,EAAE;gBAClB,aAAa;gBACb,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,YAAY,EAAE,CAAC;gBACf,QAAQ;gBACR,MAAM;gBACN,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC;YAEF,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;YAE5C,8CAA8C;YAC9C,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAExC,2DAA2D;YAC3D,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,eAAe,QAAQ,SAAS;qBACvC;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;qBACzE;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc,CAAC,QAAgB,EAAE,MAAW;QACxD,MAAM,SAAS,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEvD,iDAAiD;QACjD,IAAI,KAAa,CAAC;QAClB,IAAI,KAAa,CAAC;QAElB,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,gBAAgB;gBACnB,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;gBACrB,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,kBAAkB,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;gBACxF,MAAM;YAER,KAAK,iBAAiB;gBACpB,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;gBACvB,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,kBAAkB,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;gBACxF,MAAM;YAER,KAAK,qBAAqB;gBACxB,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;gBACrB,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,qBAAqB,CAAC;gBAC9C,MAAM;YAER;gBACE,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,2BAA2B;QAC3B,MAAM,OAAO,GAAG;YACd,KAAK;YACL,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACrD,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,GAAG;YACtC,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;YAC3D,GAAG,CAAC,MAAM,CAAC,oBAAoB,IAAI,EAAE,oBAAoB,EAAE,MAAM,CAAC,oBAAoB,EAAE,CAAC;YACzF,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC;YACpE,GAAG,CAAC,MAAM,CAAC,wBAAwB,IAAI;gBACrC,wBAAwB,EAAE,MAAM,CAAC,wBAAwB;aAC1D,CAAC;SACH,CAAC;QAEF,OAAO,MAAM,SAAS,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,oBAAoB,CAAC,QAAgB,EAAE,MAAW;QAC9D,6DAA6D;QAC7D,MAAM,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC3F,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAEjE,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,gBAAgB;gBACnB,OAAO,MAAM,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAExD,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC/D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YAChF,CAAC;YAED,KAAK,qBAAqB,CAAC,CAAC,CAAC;gBAC3B,MAAM,cAAc,GAAG,MAAM,wBAAwB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC3E,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACxF,CAAC;YAED;gBACE,MAAM,IAAI,KAAK,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,qBAAqB,CAAC,KAAa;QAC/C,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,MAAM,SAAS,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAC1B,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,+BAA+B;QAEpD,MAAM,oBAAoB,GAAG,KAAK,IAAI,EAAE;YACtC,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBAErD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC9B,uBAAuB;oBACvB,OAAO;gBACT,CAAC;gBAED,SAAS,EAAE,CAAC;gBAEZ,yCAAyC;gBACzC,MAAM,cAAc,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;gBAEtE,IAAI,cAAc,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;oBAC9C,wCAAwC;oBACxC,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;oBAC3D,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;oBACnE,iBAAiB,GAAG,cAAc,CAAC,MAAM,CAAC;gBAC5C,CAAC;gBAED,8CAA8C;gBAC9C,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,YAAY,GAAG,EAAE,EAAE,CAAC;oBAC9D,MAAM,IAAI,CAAC,kBAAkB,CAC3B,KAAK,EACL,mCAAmC,EACnC,SAAS,CAAC,MAAM,CACjB,CAAC;oBACF,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC;gBAC1B,CAAC;gBAED,oBAAoB;gBACpB,IAAI,SAAS,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;oBACrC,+BAA+B;oBAC/B,IAAI,cAAc,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;wBAC9C,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;wBAC7D,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;oBACvE,CAAC;oBAED,+CAA+C;oBAC/C,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBAEjD,4BAA4B;oBAC5B,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,EAAE,WAAW,CAAC,CAAC;oBAErE,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAC5B,OAAO;gBACT,CAAC;qBAAM,IAAI,SAAS,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;oBACzC,MAAM,IAAI,CAAC,kBAAkB,CAC3B,KAAK,EACL,qBAAqB,SAAS,CAAC,KAAK,IAAI,eAAe,EAAE,EACzD,QAAQ,CACT,CAAC;oBACF,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAC5B,OAAO;gBACT,CAAC;gBAED,2CAA2C;gBAC3C,IACE,SAAS,GAAG,QAAQ;oBACpB,CAAC,SAAS,CAAC,MAAM,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,EAClE,CAAC;oBACD,UAAU,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC,CAAC,qDAAqD;gBAC/F,CAAC;qBAAM,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;oBACjC,kBAAkB;oBAClB,MAAM,IAAI,CAAC,kBAAkB,CAC3B,KAAK,EACL,yCAAyC,EACzC,QAAQ,CACT,CAAC;oBACF,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,qBAAqB,KAAK,GAAG,EAAE,KAAK,CAAC,CAAC;gBACpD,MAAM,IAAI,CAAC,kBAAkB,CAC3B,KAAK,EACL,gBAAgB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EACxE,QAAQ,CACT,CAAC;gBACF,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC;QAEF,4BAA4B;QAC5B,UAAU,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC,CAAC,oBAAoB;IAC7D,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB,CAC9B,KAAqB,EACrB,OAAe,EACf,MAAc;QAEd,IAAI,CAAC;YACH,2DAA2D;YAC3D,gFAAgF;YAChF,MAAM,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;gBAC9B,MAAM,EAAE,uBAAuB;gBAC/B,MAAM,EAAE;oBACN,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,kBAAkB,KAAK,CAAC,QAAQ,EAAE;oBAC1C,IAAI,EAAE;wBACJ,IAAI,EAAE,eAAe;wBACrB,OAAO,EAAE,OAAO;wBAChB,MAAM,EAAE,KAAK,CAAC,KAAK;wBACnB,MAAM,EAAE,MAAM;wBACd,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;qBACtB;iBACF;aACK,CAAC,CAAC;YAEV,0DAA0D;YAC1D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,sBAAsB,CAAC,KAAa;QAChD,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,MAAM,SAAS,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,+BAA+B;QAEpD,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;YAC9B,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBAErD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC9B,uBAAuB;oBACvB,OAAO;gBACT,CAAC;gBAED,SAAS,EAAE,CAAC;gBAEZ,sDAAsD;gBACtD,IAAI,QAAQ,GAAG,KAAK,CAAC,YAAY,CAAC;gBAClC,IAAI,KAAK,GAAG,GAAG,CAAC;gBAEhB,QAAQ,SAAS,CAAC,MAAM,EAAE,CAAC;oBACzB,KAAK,SAAS;wBACZ,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,SAAS,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC5C,MAAM;oBACR,KAAK,SAAS;wBACZ,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,SAAS,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC5C,MAAM;oBACR,KAAK,WAAW;wBACd,QAAQ,GAAG,GAAG,CAAC;wBACf,MAAM;oBACR,KAAK,QAAQ;wBACX,QAAQ,GAAG,CAAC,CAAC;wBACb,KAAK,GAAG,CAAC,CAAC;wBACV,MAAM;gBACV,CAAC;gBAED,kDAAkD;gBAClD,IACE,QAAQ,GAAG,KAAK,CAAC,YAAY;oBAC7B,SAAS,CAAC,MAAM,KAAK,WAAW;oBAChC,SAAS,CAAC,MAAM,KAAK,QAAQ,EAC7B,CAAC;oBACD,MAAM,IAAI,CAAC,wBAAwB,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;oBACvE,KAAK,CAAC,YAAY,GAAG,QAAQ,CAAC;gBAChC,CAAC;gBAED,+BAA+B;gBAC/B,IAAI,SAAS,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;oBACrC,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBACjD,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAC5B,OAAO;gBACT,CAAC;qBAAM,IAAI,SAAS,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;oBACzC,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBAC9C,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAC5B,OAAO;gBACT,CAAC;gBAED,6EAA6E;gBAC7E,IACE,SAAS,GAAG,QAAQ;oBACpB,CAAC,SAAS,CAAC,MAAM,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,EAClE,CAAC;oBACD,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,uBAAuB;gBACzD,CAAC;qBAAM,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;oBACjC,kBAAkB;oBAClB,MAAM,IAAI,CAAC,wBAAwB,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;wBAC/C,GAAG,SAAS;wBACZ,MAAM,EAAE,QAAiB;wBACzB,KAAK,EAAE,+BAA+B;qBACvC,CAAC,CAAC;oBACH,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,qBAAqB,KAAK,GAAG,EAAE,KAAK,CAAC,CAAC;gBACpD,0BAA0B;gBAC1B,MAAM,IAAI,CAAC,wBAAwB,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;oBAC/C,EAAE,EAAE,KAAK;oBACT,MAAM,EAAE,QAAiB;oBACzB,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC7D,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;oBACzC,KAAK,EAAE,SAAS;iBACjB,CAAC,CAAC;gBACH,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC;QAEF,gBAAgB;QAChB,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,uBAAuB;IACzD,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,wBAAwB,CACpC,KAAqB,EACrB,QAAgB,EAChB,KAAa,EACb,SAAmB;QAEnB,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC;YACjD,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;YAErF,iCAAiC;YACjC,MAAM,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;gBAC9B,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE;oBACN,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,QAAQ;oBACR,KAAK;oBACL,KAAK,EAAE;wBACL,MAAM,EAAE,SAAS,CAAC,MAAM;wBACxB,MAAM,EAAE,SAAS,CAAC,EAAE;wBACpB,SAAS,EAAE,KAAK,CAAC,QAAQ;wBACzB,eAAe,EAAE,WAAW;wBAC5B,OAAO,EAAE,aAAa;wBACtB,GAAG,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC;qBACnD;iBACF;aACK,CAAC,CAAC;QACZ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,mBAAmB,CAAC,KAAa,EAAE,SAAmB;QAClE,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,IAAI,CAAC;YACH,kDAAkD;YAClD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAE5F,+CAA+C;YAC/C,MAAM,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;gBAC9B,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE;oBACN,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,QAAQ,EAAE,GAAG;oBACb,KAAK,EAAE,GAAG;oBACV,KAAK,EAAE;wBACL,MAAM,EAAE,WAAW;wBACnB,MAAM,EAAE,KAAK;wBACb,SAAS,EAAE,KAAK,CAAC,QAAQ;wBACzB,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS;wBAC7C,OAAO,EAAE,wBAAwB;wBACjC,YAAY,EAAE,WAAW;qBAC1B;iBACF;aACK,CAAC,CAAC;QACZ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,KAAK,GAAG,EAAE,KAAK,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,gBAAgB,CAAC,KAAa,EAAE,SAAmB;QAC/D,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,MAAM,IAAI,CAAC,wBAAwB,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,mBAAmB,CAC/B,QAAgB,EAChB,MAAW,EACX,SAAmB;QAEnB,2BAA2B;QAC3B,IAAI,MAAM,CAAC,WAAW,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;YACnE,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;YACxD,MAAM,EAAE,4BAA4B,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;YAE7E,MAAM,WAAW,GACf,MAAM,CAAC,YAAY,IAAI,CAAC,MAAM,4BAA4B,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YACtF,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YAEvD,MAAM,aAAa,GAAG;gBACpB,GAAG,IAAI,CAAC,MAAM;gBACd,YAAY,EAAE,YAAY,WAAW,IAAI,UAAU,EAAE;aACtD,CAAC;YAEF,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,aAAa,CAAC,CAAC;YAEzD,IAAI,aAAqB,CAAC;YAE1B,QAAQ,QAAQ,EAAE,CAAC;gBACjB,KAAK,gBAAgB;oBACnB,aAAa,GAAG,yCAAyC,MAAM,CAAC,KAAK,gBAAgB,SAAS,CAAC,KAAK,oBAAoB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,sBAAsB,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;oBAC7M,MAAM;gBAER,KAAK,qBAAqB;oBACxB,aAAa,GAAG,mCAAmC,MAAM,CAAC,KAAK,gBAAgB,SAAS,CAAC,KAAK,oBAAoB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,8BAA8B,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;oBAC/M,MAAM;gBAER,KAAK,iBAAiB;oBACpB,aAAa,GAAG,iCAAiC,MAAM,CAAC,OAAO,gBAAgB,SAAS,CAAC,KAAK,oBAAoB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,sBAAsB,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;oBACvM,MAAM;gBAER;oBACE,aAAa,GAAG,KAAK,QAAQ,cAAc,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACtF,CAAC;YAED,MAAM,cAAc,CAAC,UAAU,CAAC,aAAa,EAAE,GAAG,QAAQ,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC9E,CAAC;QAED,OAAO;YACL,MAAM,EAAE,SAAS,CAAC,EAAE;YACpB,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,QAAQ,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,qBAAqB;YAC3E,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;SAClD,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,MAAc,EAAE,QAAgB,EAAE,WAAmB;QAC5E,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QAEtD,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,SAAS;gBACZ,OAAO,qCAAqC,cAAc,IAAI,CAAC;YACjE,KAAK,SAAS;gBACZ,OAAO,iBAAiB,QAAQ,eAAe,cAAc,IAAI,CAAC;YACpE,KAAK,WAAW;gBACd,OAAO,4BAA4B,cAAc,UAAU,CAAC;YAC9D,KAAK,QAAQ;gBACX,OAAO,eAAe,cAAc,IAAI,CAAC;YAC3C;gBACE,OAAO,WAAW,MAAM,KAAK,cAAc,IAAI,CAAC;QACpD,CAAC;IACH,CAAC;IAED;;OAEG;IACI,eAAe,CAAC,KAAa;QAClC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,gBAAgB;QACrB,OAAO,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ import type { AsyncPerplexityParams, CheckAsyncParams, Config, AsyncJob, ErrorResponse } from '../types.js';
2
+ /**
3
+ * Handles the async_perplexity tool - creates async jobs for long-running queries
4
+ */
5
+ export declare function handleAsyncPerplexity(params: AsyncPerplexityParams, config: Config): Promise<(AsyncJob & {
6
+ selected_model: string;
7
+ model_selection_reason: string;
8
+ estimated_completion: string;
9
+ }) | ErrorResponse>;
10
+ /**
11
+ * Handles the check_async_perplexity tool - checks status of async jobs
12
+ */
13
+ export declare function handleCheckAsync(params: CheckAsyncParams, config: Config): Promise<(AsyncJob & {
14
+ completion_percentage?: number;
15
+ next_check_recommended?: string;
16
+ }) | ErrorResponse>;
17
+ /**
18
+ * Handles the list_async_jobs tool - lists all async jobs
19
+ */
20
+ export declare function handleListAsyncJobs(config: Config, limit?: number, nextToken?: string): Promise<{
21
+ jobs: (AsyncJob & {
22
+ time_since_created: string;
23
+ estimated_time_remaining?: string;
24
+ })[];
25
+ next_token?: string;
26
+ total_jobs: number;
27
+ } | ErrorResponse>;
28
+ //# sourceMappingURL=async.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async.d.ts","sourceRoot":"","sources":["../../src/tools/async.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,gBAAgB,EAChB,MAAM,EACN,QAAQ,EACR,aAAa,EACd,MAAM,aAAa,CAAC;AAIrB;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,qBAAqB,EAC7B,MAAM,EAAE,MAAM,GACb,OAAO,CACN,CAAC,QAAQ,GAAG;IACV,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC,GACF,aAAa,CAChB,CAyCA;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CACN,CAAC,QAAQ,GAAG;IACV,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC,GACF,aAAa,CAChB,CA0CA;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,KAAK,SAAK,EACV,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CACN;IACE,IAAI,EAAE,CAAC,QAAQ,GAAG;QAAE,kBAAkB,EAAE,MAAM,CAAC;QAAC,wBAAwB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;IACvF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,GACD,aAAa,CAChB,CAsCA"}
@@ -0,0 +1,167 @@
1
+ import { PerplexityApiClient } from '../perplexity-api.js';
2
+ import { selectOptimalModel } from '../models.js';
3
+ /**
4
+ * Handles the async_perplexity tool - creates async jobs for long-running queries
5
+ */
6
+ export async function handleAsyncPerplexity(params, config) {
7
+ try {
8
+ const apiClient = new PerplexityApiClient(config);
9
+ // Detect project for potential report saving (not currently used)
10
+ // const { detectProjectWithSuggestions } = await import('./projects.js');
11
+ // const projectName = await detectProjectWithSuggestions(undefined, config);
12
+ // Select optimal model based on query or use explicit model
13
+ const selectedModel = selectOptimalModel(params.query, params.model, config.default_model);
14
+ // Prepare the async request
15
+ const request = {
16
+ model: selectedModel,
17
+ messages: [{ role: 'user', content: params.query }],
18
+ temperature: params.temperature ?? 0.2,
19
+ ...(params.max_tokens && { max_tokens: params.max_tokens }),
20
+ };
21
+ const response = await apiClient.createAsyncChatCompletion(request);
22
+ // Estimate completion time based on model type and complexity
23
+ const estimatedMinutes = getEstimatedCompletionTime(selectedModel, params.query);
24
+ const estimatedCompletion = new Date(Date.now() + estimatedMinutes * 60 * 1000).toISOString();
25
+ return {
26
+ ...response,
27
+ selected_model: selectedModel,
28
+ model_selection_reason: params.model ? 'user_specified' : 'auto_selected',
29
+ estimated_completion: estimatedCompletion,
30
+ };
31
+ }
32
+ catch (error) {
33
+ return PerplexityApiClient.handleError(error, {
34
+ model: params.model || config.default_model,
35
+ query: params.query,
36
+ });
37
+ }
38
+ }
39
+ /**
40
+ * Handles the check_async_perplexity tool - checks status of async jobs
41
+ */
42
+ export async function handleCheckAsync(params, config) {
43
+ try {
44
+ const apiClient = new PerplexityApiClient(config);
45
+ // Note: async job checking doesn't need project-aware config since
46
+ // job IDs are global and not project-specific
47
+ const response = await apiClient.getAsyncJob(params.job_id);
48
+ // Add helpful metadata for job monitoring
49
+ let completionPercentage;
50
+ let nextCheckRecommended;
51
+ switch (response.status) {
52
+ case 'CREATED':
53
+ completionPercentage = 10;
54
+ nextCheckRecommended = new Date(Date.now() + 30 * 1000).toISOString(); // 30 seconds
55
+ break;
56
+ case 'STARTED':
57
+ completionPercentage = 50;
58
+ nextCheckRecommended = new Date(Date.now() + 60 * 1000).toISOString(); // 1 minute
59
+ break;
60
+ case 'COMPLETED':
61
+ completionPercentage = 100;
62
+ break;
63
+ case 'FAILED':
64
+ completionPercentage = 0;
65
+ break;
66
+ }
67
+ return {
68
+ ...response,
69
+ ...(completionPercentage !== undefined && { completion_percentage: completionPercentage }),
70
+ ...(nextCheckRecommended && { next_check_recommended: nextCheckRecommended }),
71
+ };
72
+ }
73
+ catch (error) {
74
+ return PerplexityApiClient.handleError(error, {
75
+ query: `Async job check: ${params.job_id}`,
76
+ });
77
+ }
78
+ }
79
+ /**
80
+ * Handles the list_async_jobs tool - lists all async jobs
81
+ */
82
+ export async function handleListAsyncJobs(config, limit = 20, nextToken) {
83
+ try {
84
+ const apiClient = new PerplexityApiClient(config);
85
+ // Note: listing async jobs doesn't need project-aware config since
86
+ // jobs are listed globally, not per project
87
+ const response = await apiClient.listAsyncJobs(limit, nextToken);
88
+ // Add helpful metadata to each job
89
+ const enrichedJobs = (response.jobs || []).map(job => {
90
+ const timeSinceCreated = formatTimeDuration(Date.now() - job.created_at * 1000);
91
+ let estimatedTimeRemaining;
92
+ // Estimate remaining time for active jobs
93
+ if (job.status === 'CREATED' || job.status === 'STARTED') {
94
+ const elapsedMinutes = (Date.now() - job.created_at * 1000) / (1000 * 60);
95
+ const estimatedTotalMinutes = getEstimatedCompletionTime(job.model, 'complex query');
96
+ const remainingMinutes = Math.max(0, estimatedTotalMinutes - elapsedMinutes);
97
+ estimatedTimeRemaining = `${Math.ceil(remainingMinutes)} minutes`;
98
+ }
99
+ return {
100
+ ...job,
101
+ time_since_created: timeSinceCreated,
102
+ ...(estimatedTimeRemaining && { estimated_time_remaining: estimatedTimeRemaining }),
103
+ };
104
+ });
105
+ return {
106
+ jobs: enrichedJobs,
107
+ ...(response.next_token && { next_token: response.next_token }),
108
+ total_jobs: (response.jobs || []).length,
109
+ };
110
+ }
111
+ catch (error) {
112
+ return PerplexityApiClient.handleError(error, {
113
+ query: 'List async jobs',
114
+ });
115
+ }
116
+ }
117
+ /**
118
+ * Estimates completion time based on model and query complexity
119
+ */
120
+ function getEstimatedCompletionTime(model, query) {
121
+ // Base times in minutes
122
+ const baseTimes = {
123
+ sonar: 0.5,
124
+ 'sonar-pro': 1,
125
+ 'sonar-reasoning': 1.5,
126
+ 'sonar-reasoning-pro': 3,
127
+ 'sonar-deep-research': 5,
128
+ };
129
+ let baseTime = baseTimes[model] || 2;
130
+ // Adjust based on query complexity
131
+ const queryLength = query.length;
132
+ const complexityKeywords = [
133
+ 'comprehensive',
134
+ 'detailed',
135
+ 'analysis',
136
+ 'research',
137
+ 'compare',
138
+ 'evaluate',
139
+ 'investigate',
140
+ ];
141
+ // Add time for query length
142
+ if (queryLength > 500)
143
+ baseTime *= 1.5;
144
+ else if (queryLength > 200)
145
+ baseTime *= 1.2;
146
+ // Add time for complexity keywords
147
+ const complexityScore = complexityKeywords.reduce((score, keyword) => score + (query.toLowerCase().includes(keyword) ? 1 : 0), 0);
148
+ baseTime *= 1 + complexityScore * 0.3;
149
+ return Math.ceil(baseTime);
150
+ }
151
+ /**
152
+ * Formats time duration in a human-readable format
153
+ */
154
+ function formatTimeDuration(milliseconds) {
155
+ const seconds = Math.floor(milliseconds / 1000);
156
+ const minutes = Math.floor(seconds / 60);
157
+ const hours = Math.floor(minutes / 60);
158
+ const days = Math.floor(hours / 24);
159
+ if (days > 0)
160
+ return `${days}d ${hours % 24}h`;
161
+ if (hours > 0)
162
+ return `${hours}h ${minutes % 60}m`;
163
+ if (minutes > 0)
164
+ return `${minutes}m ${seconds % 60}s`;
165
+ return `${seconds}s`;
166
+ }
167
+ //# sourceMappingURL=async.js.map