File size: 3,899 Bytes
f0743f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { useCallback, memo, ReactNode } from 'react';
import { Spinner } from '@librechat/client';
import { ChevronDownIcon, LucideProps } from 'lucide-react';
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/react';
import type { TResPlugin, TInput } from 'librechat-data-provider';
import { useGetEndpointsQuery } from '~/data-provider';
import { useShareContext } from '~/Providers';
import { cn, formatJSON } from '~/utils';
import CodeBlock from './CodeBlock';

type PluginIconProps = LucideProps & {
  className?: string;
};

function formatInputs(inputs: TInput[]) {
  let output = '';

  for (let i = 0; i < inputs.length; i++) {
    const input = formatJSON(`${inputs[i]?.inputStr ?? inputs[i]}`);
    output += input;

    if (inputs.length > 1 && i !== inputs.length - 1) {
      output += ',\n';
    }
  }

  return output;
}

type PluginProps = {
  plugin: TResPlugin;
};

const Plugin: React.FC<PluginProps> = ({ plugin }) => {
  const { isSharedConvo } = useShareContext();
  const { data: plugins = {} } = useGetEndpointsQuery({
    enabled: !isSharedConvo,
    select: (data) => data?.gptPlugins?.plugins,
  });

  const getPluginName = useCallback(
    (pluginKey: string) => {
      if (!pluginKey) {
        return null;
      }

      if (pluginKey === 'n/a' || pluginKey === 'self reflection') {
        return pluginKey;
      }
      return plugins[pluginKey] ?? 'self reflection';
    },
    [plugins],
  );

  if (!plugin || !plugin.latest) {
    return null;
  }

  const latestPlugin = getPluginName(plugin.latest);

  if (!latestPlugin || (latestPlugin && latestPlugin === 'n/a')) {
    return null;
  }

  const generateStatus = (): ReactNode => {
    if (!plugin.loading && latestPlugin === 'self reflection') {
      return 'Finished';
    } else if (latestPlugin === 'self reflection') {
      return "I'm  thinking...";
    } else {
      return (
        <>
          {plugin.loading ? 'Using' : 'Used'} <b>{latestPlugin}</b>
          {plugin.loading ? '...' : ''}
        </>
      );
    }
  };

  return (
    <div className="my-2 flex flex-col items-start">
      <Disclosure>
        {({ open }) => {
          const iconProps: PluginIconProps = {
            className: cn(open ? 'rotate-180 transform' : '', 'h-4 w-4'),
          };
          return (
            <>
              <div
                className={cn(
                  plugin.loading ? 'bg-green-100' : 'bg-gray-20',
                  'my-1 flex items-center rounded p-3 text-xs text-gray-800',
                )}
              >
                <div>
                  <div className="flex items-center gap-3">
                    <div>{generateStatus()}</div>
                  </div>
                </div>
                {plugin.loading && <Spinner className="ml-1 text-black" />}
                <DisclosureButton className="ml-12 flex items-center gap-2">
                  <ChevronDownIcon {...iconProps} />
                </DisclosureButton>
              </div>

              <DisclosurePanel className="mt-3 flex max-w-full flex-col gap-3">
                <CodeBlock
                  lang={latestPlugin ? `REQUEST TO ${latestPlugin.toUpperCase()}` : 'REQUEST'}
                  codeChildren={formatInputs(plugin.inputs ?? [])}
                  plugin={true}
                  classProp="max-h-[450px]"
                />
                {plugin.outputs && plugin.outputs.length > 0 && (
                  <CodeBlock
                    lang={latestPlugin ? `RESPONSE FROM ${latestPlugin.toUpperCase()}` : 'RESPONSE'}
                    codeChildren={formatJSON(plugin.outputs ?? '')}
                    plugin={true}
                    classProp="max-h-[450px]"
                  />
                )}
              </DisclosurePanel>
            </>
          );
        }}
      </Disclosure>
    </div>
  );
};

export default memo(Plugin);