floating-copilot-widget 1.4.3 → 1.5.1

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.
package/dist/index.js CHANGED
@@ -261,6 +261,835 @@ const FloatingCopilot = ({ config = {} }) => {
261
261
  finalConfig.resizable && !isMaximized && (React.createElement("div", { className: "copilot-resize-handle", onMouseDown: handleMouseDownResize, title: "Drag to resize" }))));
262
262
  };
263
263
 
264
+ /******************************************************************************
265
+ Copyright (c) Microsoft Corporation.
266
+
267
+ Permission to use, copy, modify, and/or distribute this software for any
268
+ purpose with or without fee is hereby granted.
269
+
270
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
271
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
272
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
273
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
274
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
275
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
276
+ PERFORMANCE OF THIS SOFTWARE.
277
+ ***************************************************************************** */
278
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
279
+
280
+
281
+ function __awaiter(thisArg, _arguments, P, generator) {
282
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
283
+ return new (P || (P = Promise))(function (resolve, reject) {
284
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
285
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
286
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
287
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
288
+ });
289
+ }
290
+
291
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
292
+ var e = new Error(message);
293
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
294
+ };
295
+
296
+ /**
297
+ * GitHub Copilot Integration Service
298
+ *
299
+ * Provides AI-powered intent analysis and API integration for the floating chat widget.
300
+ * Uses GitHub's Models API (backed by OpenAI GPT-4) for intelligent message understanding.
301
+ *
302
+ * To use this service, you need a GitHub Personal Access Token with appropriate scopes.
303
+ */
304
+ const GITHUB_COPILOT_MODELS = 'https://models.inference.ai.azure.com/chat/completions';
305
+ /**
306
+ * Get GitHub token from config or environment variables
307
+ */
308
+ function getGithubToken(configToken) {
309
+ var _a, _b, _c;
310
+ // 1. Use explicitly provided token from config
311
+ if (configToken) {
312
+ return configToken;
313
+ }
314
+ // 2. Check common environment variable names
315
+ const token = (typeof process !== 'undefined' && ((_a = process.env) === null || _a === void 0 ? void 0 : _a.GITHUB_TOKEN)) ||
316
+ (typeof process !== 'undefined' && ((_b = process.env) === null || _b === void 0 ? void 0 : _b.VITE_GITHUB_TOKEN)) ||
317
+ (typeof process !== 'undefined' && ((_c = process.env) === null || _c === void 0 ? void 0 : _c.REACT_APP_GITHUB_TOKEN)) ||
318
+ (typeof window !== 'undefined' && window.__GITHUB_TOKEN__);
319
+ if (!token) {
320
+ throw new Error('GitHub token is required for Copilot integration. ' +
321
+ 'Provide it via:\n' +
322
+ '1. CopilotConfig.githubToken parameter\n' +
323
+ '2. Environment variable: GITHUB_TOKEN, VITE_GITHUB_TOKEN, or REACT_APP_GITHUB_TOKEN\n' +
324
+ '3. Global variable: window.__GITHUB_TOKEN__\n\n' +
325
+ 'Get token from: https://github.com/settings/tokens (scopes: copilot, read:user)');
326
+ }
327
+ return token;
328
+ }
329
+ /**
330
+ * Analyze user message to identify intent and extract parameters
331
+ */
332
+ function analyzeUserIntent(request, config, availableApis) {
333
+ var _a, _b, _c;
334
+ return __awaiter(this, void 0, void 0, function* () {
335
+ const { userMessage, context, customInstructions } = request;
336
+ const { model = 'gpt-4o', maxTokens = 2000 } = config;
337
+ const githubToken = getGithubToken(config.githubToken);
338
+ // Build system prompt
339
+ const systemPrompt = buildIntentSystemPrompt(availableApis, customInstructions);
340
+ // Build user prompt
341
+ const userPrompt = buildIntentUserPrompt(userMessage, context);
342
+ try {
343
+ const response = yield fetch(GITHUB_COPILOT_MODELS, {
344
+ method: 'POST',
345
+ headers: {
346
+ 'Authorization': `Bearer ${githubToken}`,
347
+ 'Content-Type': 'application/json',
348
+ 'X-GitHub-Api-Version': '2022-11-28'
349
+ },
350
+ body: JSON.stringify({
351
+ model: model,
352
+ messages: [
353
+ { role: 'system', content: systemPrompt },
354
+ { role: 'user', content: userPrompt }
355
+ ],
356
+ max_tokens: maxTokens,
357
+ temperature: 0.3
358
+ })
359
+ });
360
+ if (!response.ok) {
361
+ const errorText = yield response.text();
362
+ throw new Error(`Copilot API error (${response.status}): ${errorText}`);
363
+ }
364
+ const data = yield response.json();
365
+ const content = (_c = (_b = (_a = data.choices) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) === null || _c === void 0 ? void 0 : _c.content;
366
+ if (!content) {
367
+ throw new Error('No response received from Copilot');
368
+ }
369
+ // Parse the intent response
370
+ return parseIntentResponse(content, userMessage);
371
+ }
372
+ catch (error) {
373
+ throw new Error(`Failed to analyze intent: ${error.message}`);
374
+ }
375
+ });
376
+ }
377
+ /**
378
+ * Call an API integration based on intent and parameters
379
+ */
380
+ function callAPI(request, integration) {
381
+ return __awaiter(this, void 0, void 0, function* () {
382
+ try {
383
+ // Build the request
384
+ const apiRequest = integration.buildRequest(request.parameters, request.context);
385
+ // Prepare fetch options
386
+ const fetchOptions = {
387
+ method: integration.method,
388
+ headers: Object.assign({ 'Content-Type': 'application/json' }, integration.headers)
389
+ };
390
+ // Add body for non-GET requests
391
+ if (integration.method !== 'GET' && apiRequest) {
392
+ fetchOptions.body = typeof apiRequest === 'string' ? apiRequest : JSON.stringify(apiRequest);
393
+ }
394
+ // Make the API call
395
+ const response = yield fetch(integration.endpoint, fetchOptions);
396
+ if (!response.ok) {
397
+ const errorText = yield response.text();
398
+ return {
399
+ success: false,
400
+ error: `API error (${response.status}): ${errorText}`,
401
+ apiName: integration.name
402
+ };
403
+ }
404
+ const responseData = yield response.json();
405
+ // Format the response
406
+ const formattedData = integration.formatResponse(responseData);
407
+ return {
408
+ success: true,
409
+ data: formattedData,
410
+ rawData: responseData,
411
+ apiName: integration.name
412
+ };
413
+ }
414
+ catch (error) {
415
+ return {
416
+ success: false,
417
+ error: `Failed to call API: ${error.message}`,
418
+ apiName: integration.name
419
+ };
420
+ }
421
+ });
422
+ }
423
+ /**
424
+ * Process user message: analyze intent and call appropriate API
425
+ */
426
+ function processUserMessage(userMessage, config, availableApis, context) {
427
+ return __awaiter(this, void 0, void 0, function* () {
428
+ // Validate token is available early
429
+ getGithubToken(config.githubToken);
430
+ // Step 1: Analyze intent
431
+ const intentResponse = yield analyzeUserIntent({ userMessage, context }, config, availableApis);
432
+ // Step 2: Determine which API to call
433
+ let apiResponse;
434
+ if (intentResponse.suggestedApis.length > 0) {
435
+ const apiId = intentResponse.suggestedApis[0];
436
+ const api = availableApis.find(a => a.id === apiId);
437
+ if (api) {
438
+ // Check if API should be called for this intent
439
+ const shouldCall = api.shouldCall
440
+ ? api.shouldCall(intentResponse.intent, intentResponse.parameters)
441
+ : true;
442
+ if (shouldCall) {
443
+ apiResponse = yield callAPI({
444
+ apiId,
445
+ parameters: intentResponse.parameters,
446
+ context
447
+ }, api);
448
+ }
449
+ }
450
+ }
451
+ return {
452
+ intent: intentResponse,
453
+ apiResponse
454
+ };
455
+ });
456
+ }
457
+ /**
458
+ * Validate that GitHub token is available before processing
459
+ * Useful for early validation in applications
460
+ */
461
+ function validateGithubToken(config) {
462
+ try {
463
+ const token = getGithubToken(config.githubToken);
464
+ return { valid: true, token };
465
+ }
466
+ catch (error) {
467
+ return { valid: false, error: error.message };
468
+ }
469
+ }
470
+ /**
471
+ * Generate a user-friendly response from intent and API data
472
+ */
473
+ function generateCopilotResponse(userMessage, intentResponse, apiResponse, config) {
474
+ return __awaiter(this, void 0, void 0, function* () {
475
+ // If we have API response data, return it
476
+ if ((apiResponse === null || apiResponse === void 0 ? void 0 : apiResponse.success) && apiResponse.data) {
477
+ return apiResponse.data;
478
+ }
479
+ // If API call failed, explain the error
480
+ if (apiResponse === null || apiResponse === void 0 ? void 0 : apiResponse.error) {
481
+ return `I encountered an error while processing your request: ${apiResponse.error}`;
482
+ }
483
+ // If no API was called but we have intent analysis
484
+ if (intentResponse.intent && intentResponse.confidence > 0.5) {
485
+ return `I understand you want to: ${intentResponse.intent}
486
+
487
+ Parameters identified:
488
+ ${Object.entries(intentResponse.parameters)
489
+ .map(([key, value]) => `- ${key}: ${JSON.stringify(value)}`)
490
+ .join('\n')}
491
+
492
+ However, no API integration is available for this intent. Please check the available integrations.`;
493
+ }
494
+ // Fallback response
495
+ return `I'm not sure what you're asking. Could you provide more details?`;
496
+ });
497
+ }
498
+ /**
499
+ * Build system prompt for intent analysis
500
+ */
501
+ function buildIntentSystemPrompt(availableApis, customInstructions) {
502
+ let prompt = `You are an intelligent intent analyzer integrated into a chat application.
503
+ Your role is to understand user messages and identify the user's intent, extract relevant parameters, and suggest which API integrations to use.
504
+
505
+ RESPONSE FORMAT:
506
+ You MUST respond ONLY with a valid JSON object in this exact format:
507
+ {
508
+ "intent": "description of what the user wants",
509
+ "confidence": 0.95,
510
+ "parameters": {
511
+ "param1": "value1",
512
+ "param2": "value2"
513
+ },
514
+ "suggestedApis": ["api_id_1", "api_id_2"]
515
+ }
516
+
517
+ IMPORTANT:
518
+ - intent: A clear description of what the user wants to accomplish
519
+ - confidence: A number between 0 and 1 indicating how confident you are
520
+ - parameters: Key-value pairs of information extracted from the message
521
+ - suggestedApis: Array of API IDs that should be called (in order of preference)
522
+
523
+ Be conversational, helpful, and focus on understanding the user's actual need.`;
524
+ if (availableApis && availableApis.length > 0) {
525
+ prompt += `\n\nAVAILABLE API INTEGRATIONS:\n`;
526
+ availableApis.forEach(api => {
527
+ prompt += `\n- ID: ${api.id}\n Name: ${api.name}\n Description: ${api.name}`;
528
+ if (api.intents) {
529
+ prompt += `\n Intended for intents: ${api.intents.join(', ')}`;
530
+ }
531
+ });
532
+ }
533
+ if (customInstructions) {
534
+ prompt += `\n\nCUSTOM INSTRUCTIONS:\n${customInstructions}`;
535
+ }
536
+ return prompt;
537
+ }
538
+ /**
539
+ * Build user prompt for intent analysis
540
+ */
541
+ function buildIntentUserPrompt(userMessage, context, availableApis) {
542
+ let prompt = `Analyze this user message and respond with ONLY a valid JSON object (no markdown, no extra text):
543
+
544
+ User message: "${userMessage}"`;
545
+ if (context && Object.keys(context).length > 0) {
546
+ prompt += `\n\nContext information:\n`;
547
+ Object.entries(context).forEach(([key, value]) => {
548
+ prompt += `- ${key}: ${JSON.stringify(value)}\n`;
549
+ });
550
+ }
551
+ prompt += `\n\nRespond with ONLY the JSON object, no other text.`;
552
+ return prompt;
553
+ }
554
+ /**
555
+ * Parse intent response from Copilot
556
+ */
557
+ function parseIntentResponse(content, userMessage) {
558
+ try {
559
+ // Extract JSON from potential markdown code blocks
560
+ let jsonContent = content.trim();
561
+ const jsonMatch = content.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
562
+ if (jsonMatch) {
563
+ jsonContent = jsonMatch[1];
564
+ }
565
+ const parsed = JSON.parse(jsonContent);
566
+ return {
567
+ intent: parsed.intent || 'unknown',
568
+ confidence: typeof parsed.confidence === 'number' ? parsed.confidence : 0.5,
569
+ parameters: parsed.parameters || {},
570
+ suggestedApis: Array.isArray(parsed.suggestedApis) ? parsed.suggestedApis : [],
571
+ rawResponse: content
572
+ };
573
+ }
574
+ catch (error) {
575
+ // Fallback parsing if JSON parsing fails
576
+ return {
577
+ intent: 'user_query',
578
+ confidence: 0.3,
579
+ parameters: { query: userMessage },
580
+ suggestedApis: [],
581
+ rawResponse: content
582
+ };
583
+ }
584
+ }
585
+ /**
586
+ * Validate API integration configuration
587
+ */
588
+ function validateAPIIntegration(api) {
589
+ const errors = [];
590
+ if (!api.id)
591
+ errors.push('API must have an id');
592
+ if (!api.name)
593
+ errors.push('API must have a name');
594
+ if (!api.endpoint)
595
+ errors.push('API must have an endpoint');
596
+ if (!api.method)
597
+ errors.push('API must have a method');
598
+ if (!api.buildRequest || typeof api.buildRequest !== 'function') {
599
+ errors.push('API must have a buildRequest function');
600
+ }
601
+ if (!api.formatResponse || typeof api.formatResponse !== 'function') {
602
+ errors.push('API must have a formatResponse function');
603
+ }
604
+ return {
605
+ valid: errors.length === 0,
606
+ errors
607
+ };
608
+ }
609
+ /**
610
+ * Merge multiple API integrations from different sources
611
+ */
612
+ function mergeAPIIntegrations(...integrationSets) {
613
+ const merged = new Map();
614
+ integrationSets.forEach(set => {
615
+ set.forEach(api => {
616
+ const validation = validateAPIIntegration(api);
617
+ if (validation.valid) {
618
+ merged.set(api.id, api);
619
+ }
620
+ else {
621
+ console.warn(`Invalid API integration ${api.id}:`, validation.errors);
622
+ }
623
+ });
624
+ });
625
+ return Array.from(merged.values());
626
+ }
627
+ /**
628
+ * Get missing required parameters for an API
629
+ */
630
+ function getMissingParameters(api, providedParams) {
631
+ if (!api.requiredParameters || api.requiredParameters.length === 0) {
632
+ return [];
633
+ }
634
+ return api.requiredParameters
635
+ .filter(param => param.required !== false && !providedParams[param.name])
636
+ .map(param => param.name);
637
+ }
638
+ /**
639
+ * Get the next missing parameter to ask for
640
+ */
641
+ function getNextMissingParameter(api, providedParams) {
642
+ if (!api.requiredParameters || api.requiredParameters.length === 0) {
643
+ return null;
644
+ }
645
+ const missing = api.requiredParameters.find(param => param.required !== false && !providedParams[param.name]);
646
+ if (!missing) {
647
+ return null;
648
+ }
649
+ return {
650
+ parameter: missing.name,
651
+ description: missing.description,
652
+ example: missing.example,
653
+ type: missing.type
654
+ };
655
+ }
656
+ /**
657
+ * Validate a parameter value against its definition
658
+ */
659
+ function validateParameter(paramName, value, definition) {
660
+ if (!value) {
661
+ return { valid: false, error: `${paramName} cannot be empty` };
662
+ }
663
+ // Type validation
664
+ if (definition.type) {
665
+ switch (definition.type) {
666
+ case 'email':
667
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
668
+ return { valid: false, error: `${paramName} must be a valid email address` };
669
+ }
670
+ break;
671
+ case 'phone':
672
+ if (!/^[\d\s\-+()]+$/.test(value) || value.replace(/\D/g, '').length < 10) {
673
+ return { valid: false, error: `${paramName} must be a valid phone number` };
674
+ }
675
+ break;
676
+ case 'number':
677
+ if (isNaN(Number(value))) {
678
+ return { valid: false, error: `${paramName} must be a number` };
679
+ }
680
+ break;
681
+ case 'date':
682
+ if (isNaN(Date.parse(value))) {
683
+ return { valid: false, error: `${paramName} must be a valid date` };
684
+ }
685
+ break;
686
+ }
687
+ }
688
+ // Regex validation
689
+ if (definition.validation) {
690
+ const regex = new RegExp(definition.validation);
691
+ if (!regex.test(value)) {
692
+ return { valid: false, error: `${paramName} format is invalid` };
693
+ }
694
+ }
695
+ return { valid: true };
696
+ }
697
+ /**
698
+ * Check if all required parameters have been collected
699
+ */
700
+ function areAllParametersCollected(api, providedParams) {
701
+ if (!api.requiredParameters || api.requiredParameters.length === 0) {
702
+ return true;
703
+ }
704
+ return !api.requiredParameters.some(param => param.required !== false && !providedParams[param.name]);
705
+ }
706
+ /**
707
+ * Collect parameters interactively
708
+ * Returns a system prompt asking for the next missing parameter
709
+ * OR triggers API call if all parameters are collected
710
+ */
711
+ function generateParameterPromptOrCallAPI(api, providedParams, intent, context) {
712
+ return __awaiter(this, void 0, void 0, function* () {
713
+ // Check if all required parameters are collected
714
+ const allCollected = areAllParametersCollected(api, providedParams);
715
+ if (allCollected) {
716
+ // All parameters are collected - call the API
717
+ try {
718
+ const apiResponse = yield callAPI({
719
+ apiId: api.id,
720
+ parameters: providedParams,
721
+ context
722
+ }, api);
723
+ return {
724
+ apiResponse,
725
+ allParametersCollected: true
726
+ };
727
+ }
728
+ catch (error) {
729
+ return {
730
+ prompt: `Error executing request: ${error.message}`,
731
+ allParametersCollected: true
732
+ };
733
+ }
734
+ }
735
+ // Still missing parameters - ask for the next one
736
+ const nextParam = getNextMissingParameter(api, providedParams);
737
+ if (!nextParam) {
738
+ return {
739
+ allParametersCollected: true
740
+ };
741
+ }
742
+ const provided = Object.keys(providedParams)
743
+ .filter(key => providedParams[key])
744
+ .map(key => `- ${key}: ${providedParams[key]}`)
745
+ .join('\n');
746
+ let prompt = `To complete your request to ${intent}, I need the following information:\n\n`;
747
+ prompt += `**${nextParam.parameter}**: ${nextParam.description}`;
748
+ if (nextParam.type) {
749
+ prompt += ` (Type: ${nextParam.type})`;
750
+ }
751
+ if (nextParam.example) {
752
+ prompt += `\nExample: ${nextParam.example}`;
753
+ }
754
+ if (provided) {
755
+ prompt += `\n\nAlready provided:\n${provided}`;
756
+ }
757
+ return {
758
+ prompt,
759
+ allParametersCollected: false
760
+ };
761
+ });
762
+ }
763
+ /**
764
+ * Collect parameters interactively
765
+ * Returns a system prompt asking for the next missing parameter
766
+ */
767
+ function generateParameterPrompt(api, providedParams) {
768
+ const nextParam = getNextMissingParameter(api, providedParams);
769
+ if (!nextParam) {
770
+ return '';
771
+ }
772
+ const provided = Object.keys(providedParams)
773
+ .filter(key => providedParams[key])
774
+ .map(key => `- ${key}: ${providedParams[key]}`)
775
+ .join('\n');
776
+ let prompt = `To complete your request, I need the following information:\n\n`;
777
+ prompt += `**${nextParam.parameter}**: ${nextParam.description}`;
778
+ if (nextParam.type) {
779
+ prompt += ` (Type: ${nextParam.type})`;
780
+ }
781
+ if (nextParam.example) {
782
+ prompt += `\nExample: ${nextParam.example}`;
783
+ }
784
+ if (provided) {
785
+ prompt += `\n\nAlready provided:\n${provided}`;
786
+ }
787
+ return prompt;
788
+ }
789
+
790
+ /**
791
+ * API Integration Examples
792
+ *
793
+ * This file provides examples of how to create and configure API integrations
794
+ * for use with the Copilot chat widget.
795
+ */
796
+ /**
797
+ * Example: Customer Creation API with Required Parameters
798
+ *
799
+ * This example shows how to integrate an API that creates a customer
800
+ * with interactive parameter collection
801
+ */
802
+ const createCustomerAPIIntegration = (baseUrl) => {
803
+ const requiredParams = [
804
+ {
805
+ name: 'name',
806
+ description: 'Customer full name',
807
+ type: 'string',
808
+ required: true,
809
+ example: 'John Doe'
810
+ },
811
+ {
812
+ name: 'email',
813
+ description: 'Customer email address',
814
+ type: 'email',
815
+ required: true,
816
+ validation: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$',
817
+ example: 'john@example.com'
818
+ },
819
+ {
820
+ name: 'phone',
821
+ description: 'Customer phone number',
822
+ type: 'phone',
823
+ required: true,
824
+ example: '+1-555-123-4567'
825
+ },
826
+ {
827
+ name: 'company',
828
+ description: 'Company name (optional)',
829
+ type: 'string',
830
+ required: false,
831
+ example: 'Acme Corp'
832
+ }
833
+ ];
834
+ return {
835
+ id: 'create_customer',
836
+ name: 'Create Customer',
837
+ endpoint: `${baseUrl}/api/customers`,
838
+ method: 'POST',
839
+ intents: ['create_customer', 'add_customer', 'new_customer'],
840
+ requiredParameters: requiredParams,
841
+ buildRequest: (params) => ({
842
+ name: params.name,
843
+ email: params.email,
844
+ phone: params.phone,
845
+ company: params.company || null,
846
+ createdAt: new Date().toISOString()
847
+ }),
848
+ formatResponse: (data) => {
849
+ return `✅ **Customer Created Successfully**\n\n` +
850
+ `**ID**: ${data.id}\n` +
851
+ `**Name**: ${data.name}\n` +
852
+ `**Email**: ${data.email}\n` +
853
+ `**Phone**: ${data.phone}\n` +
854
+ (data.company ? `**Company**: ${data.company}\n` : '') +
855
+ `**Created**: ${new Date(data.createdAt).toLocaleDateString()}`;
856
+ },
857
+ shouldCall: (intent, params) => {
858
+ // Call when all required params are present
859
+ return !!(params.name && params.email && params.phone);
860
+ }
861
+ };
862
+ };
863
+ /**
864
+ * Example: REST API Integration
865
+ *
866
+ * This example shows how to integrate a generic REST API that returns user data
867
+ */
868
+ const createUserAPIIntegration = (baseUrl) => ({
869
+ id: 'user_api',
870
+ name: 'User Service API',
871
+ endpoint: `${baseUrl}/api/users`,
872
+ method: 'GET',
873
+ intents: ['get_user', 'find_user', 'lookup_user'],
874
+ buildRequest: (params) => {
875
+ // Transform intent parameters into API query string
876
+ const queryParams = new URLSearchParams();
877
+ if (params.userId)
878
+ queryParams.append('id', params.userId);
879
+ if (params.username)
880
+ queryParams.append('username', params.username);
881
+ if (params.email)
882
+ queryParams.append('email', params.email);
883
+ return queryParams.toString();
884
+ },
885
+ formatResponse: (data) => {
886
+ if (Array.isArray(data)) {
887
+ return data.map(user => `**${user.name}** (${user.email})\nID: ${user.id}\nRole: ${user.role}`).join('\n\n');
888
+ }
889
+ return `**${data.name}** (${data.email})\nID: ${data.id}\nRole: ${data.role}`;
890
+ },
891
+ shouldCall: (intent, params) => {
892
+ // Only call if we have identifying parameters
893
+ return !!(params.userId || params.username || params.email);
894
+ }
895
+ });
896
+ /**
897
+ * Example: Data Analysis API Integration
898
+ *
899
+ * This shows how to integrate an API that performs data analysis
900
+ */
901
+ const createAnalysisAPIIntegration = (baseUrl) => ({
902
+ id: 'analysis_api',
903
+ name: 'Data Analysis Service',
904
+ endpoint: `${baseUrl}/api/analysis`,
905
+ method: 'POST',
906
+ intents: ['analyze_data', 'generate_report', 'data_insights'],
907
+ buildRequest: (params) => ({
908
+ dataSource: params.dataSource,
909
+ analysisType: params.analysisType || 'summary',
910
+ timeRange: params.timeRange,
911
+ filters: params.filters || {}
912
+ }),
913
+ formatResponse: (data) => {
914
+ let response = `## Analysis Results\n\n`;
915
+ if (data.summary) {
916
+ response += `### Summary\n${data.summary}\n\n`;
917
+ }
918
+ if (data.metrics) {
919
+ response += `### Key Metrics\n`;
920
+ Object.entries(data.metrics).forEach(([key, value]) => {
921
+ response += `- **${key}**: ${value}\n`;
922
+ });
923
+ response += '\n';
924
+ }
925
+ if (data.recommendations) {
926
+ response += `### Recommendations\n`;
927
+ data.recommendations.forEach((rec) => {
928
+ response += `- ${rec}\n`;
929
+ });
930
+ }
931
+ return response;
932
+ },
933
+ shouldCall: (intent, params) => {
934
+ return !!(params.dataSource && params.analysisType);
935
+ }
936
+ });
937
+ /**
938
+ * Example: Search API Integration
939
+ *
940
+ * Shows how to integrate a search/query API
941
+ */
942
+ const createSearchAPIIntegration = (baseUrl) => ({
943
+ id: 'search_api',
944
+ name: 'Search Service',
945
+ endpoint: `${baseUrl}/api/search`,
946
+ method: 'POST',
947
+ intents: ['search', 'find', 'query'],
948
+ buildRequest: (params) => ({
949
+ query: params.query,
950
+ filters: {
951
+ type: params.type,
952
+ category: params.category,
953
+ dateRange: params.dateRange
954
+ },
955
+ limit: params.limit || 10,
956
+ offset: params.offset || 0
957
+ }),
958
+ formatResponse: (data) => {
959
+ if (!data.results || data.results.length === 0) {
960
+ return 'No results found matching your search criteria.';
961
+ }
962
+ let response = `Found **${data.results.length}** results:\n\n`;
963
+ response += data.results.map((result, index) => `${index + 1}. **${result.title}**\n ${result.description}\n URL: ${result.url}`).join('\n\n');
964
+ return response;
965
+ }
966
+ });
967
+ /**
968
+ * Example: Webhook/Action API Integration
969
+ *
970
+ * Shows how to integrate APIs that perform actions (create, update, delete)
971
+ */
972
+ const createActionAPIIntegration = (baseUrl) => ({
973
+ id: 'action_api',
974
+ name: 'Action Service',
975
+ endpoint: `${baseUrl}/api/actions`,
976
+ method: 'POST',
977
+ intents: ['create', 'update', 'delete', 'perform_action'],
978
+ buildRequest: (params) => ({
979
+ action: params.action,
980
+ targetId: params.targetId,
981
+ targetType: params.targetType,
982
+ payload: params.payload || {},
983
+ metadata: params.metadata || {}
984
+ }),
985
+ formatResponse: (data) => {
986
+ if (data.success) {
987
+ return `✅ **Action Completed Successfully**\n\n${data.message || 'The requested action has been performed.'}\n\nDetails: ${JSON.stringify(data.result, null, 2)}`;
988
+ }
989
+ return `❌ **Action Failed**\n\n${data.message || 'The requested action could not be completed.'}`;
990
+ }
991
+ });
992
+ /**
993
+ * Example: Database Query Integration
994
+ *
995
+ * Shows how to integrate a database query service
996
+ */
997
+ const createDatabaseAPIIntegration = (baseUrl) => ({
998
+ id: 'database_api',
999
+ name: 'Database Query Service',
1000
+ endpoint: `${baseUrl}/api/query`,
1001
+ method: 'POST',
1002
+ intents: ['query_database', 'get_data', 'fetch_records'],
1003
+ buildRequest: (params) => ({
1004
+ table: params.table,
1005
+ columns: params.columns || ['*'],
1006
+ where: params.where || {},
1007
+ orderBy: params.orderBy,
1008
+ limit: params.limit || 50
1009
+ }),
1010
+ formatResponse: (data) => {
1011
+ if (!data.rows || data.rows.length === 0) {
1012
+ return 'No records found matching your query.';
1013
+ }
1014
+ let response = `Retrieved **${data.rows.length}** records:\n\n`;
1015
+ // Format as table if we have column information
1016
+ if (data.columns && data.columns.length > 0) {
1017
+ response += `| ${data.columns.join(' | ')} |\n`;
1018
+ response += `|${data.columns.map(() => '-').join('|')}|\n`;
1019
+ data.rows.forEach((row) => {
1020
+ response += `| ${data.columns.map((col) => row[col] || '-').join(' | ')} |\n`;
1021
+ });
1022
+ }
1023
+ else {
1024
+ // Fallback: display as JSON
1025
+ response += '```json\n' + JSON.stringify(data.rows, null, 2) + '\n```';
1026
+ }
1027
+ return response;
1028
+ }
1029
+ });
1030
+ /**
1031
+ * Example: External Service Integration (Weather, News, etc.)
1032
+ */
1033
+ const createWeatherAPIIntegration = (apiKey) => ({
1034
+ id: 'weather_api',
1035
+ name: 'Weather Service',
1036
+ endpoint: 'https://api.openweathermap.org/data/2.5/weather',
1037
+ method: 'GET',
1038
+ headers: {
1039
+ 'User-Agent': 'FloatingCopilot/1.0'
1040
+ },
1041
+ intents: ['get_weather', 'weather', 'check_weather'],
1042
+ buildRequest: (params) => {
1043
+ // Note: For actual use, pass apiKey securely
1044
+ return {
1045
+ q: params.city,
1046
+ appid: apiKey,
1047
+ units: params.units || 'metric'
1048
+ };
1049
+ },
1050
+ formatResponse: (data) => {
1051
+ var _a, _b, _c;
1052
+ const weather = (_a = data.weather) === null || _a === void 0 ? void 0 : _a[0];
1053
+ const main = data.main;
1054
+ return `**Weather for ${data.name}, ${(_b = data.sys) === null || _b === void 0 ? void 0 : _b.country}**
1055
+
1056
+ Current: ${weather === null || weather === void 0 ? void 0 : weather.main} (${weather === null || weather === void 0 ? void 0 : weather.description})
1057
+ Temperature: ${main === null || main === void 0 ? void 0 : main.temp}°C
1058
+ Feels like: ${main === null || main === void 0 ? void 0 : main.feels_like}°C
1059
+ Humidity: ${main === null || main === void 0 ? void 0 : main.humidity}%
1060
+ Wind Speed: ${(_c = data.wind) === null || _c === void 0 ? void 0 : _c.speed} m/s
1061
+
1062
+ Updated: ${new Date(data.dt * 1000).toLocaleString()}`;
1063
+ }
1064
+ });
1065
+ /**
1066
+ * Helper function to create a custom API integration
1067
+ */
1068
+ function createCustomAPIIntegration(config) {
1069
+ return config;
1070
+ }
1071
+
264
1072
  exports.FloatingCopilot = FloatingCopilot;
1073
+ exports.analyzeUserIntent = analyzeUserIntent;
1074
+ exports.areAllParametersCollected = areAllParametersCollected;
1075
+ exports.callAPI = callAPI;
1076
+ exports.createActionAPIIntegration = createActionAPIIntegration;
1077
+ exports.createAnalysisAPIIntegration = createAnalysisAPIIntegration;
1078
+ exports.createCustomAPIIntegration = createCustomAPIIntegration;
1079
+ exports.createCustomerAPIIntegration = createCustomerAPIIntegration;
1080
+ exports.createDatabaseAPIIntegration = createDatabaseAPIIntegration;
1081
+ exports.createSearchAPIIntegration = createSearchAPIIntegration;
1082
+ exports.createUserAPIIntegration = createUserAPIIntegration;
1083
+ exports.createWeatherAPIIntegration = createWeatherAPIIntegration;
265
1084
  exports.default = FloatingCopilot;
266
1085
  exports.defaultConfig = defaultConfig;
1086
+ exports.generateCopilotResponse = generateCopilotResponse;
1087
+ exports.generateParameterPrompt = generateParameterPrompt;
1088
+ exports.generateParameterPromptOrCallAPI = generateParameterPromptOrCallAPI;
1089
+ exports.getMissingParameters = getMissingParameters;
1090
+ exports.getNextMissingParameter = getNextMissingParameter;
1091
+ exports.mergeAPIIntegrations = mergeAPIIntegrations;
1092
+ exports.processUserMessage = processUserMessage;
1093
+ exports.validateAPIIntegration = validateAPIIntegration;
1094
+ exports.validateGithubToken = validateGithubToken;
1095
+ exports.validateParameter = validateParameter;