File size: 3,827 Bytes
3b6afc0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import React, { useState, useCallback, memo, ReactNode } from 'react';
import { Spinner } from '~/components';
import { useRecoilValue } from 'recoil';
import CodeBlock from './Content/CodeBlock.jsx';
import { Disclosure } from '@headlessui/react';
import { ChevronDownIcon, LucideProps } from 'lucide-react';
import { cn } from '~/utils/';
import store from '~/store';

interface Input {
  inputStr: string;
}

interface PluginProps {
  plugin: {
    plugin: string;
    input: string;
    thought: string;
    loading?: boolean;
    outputs?: string;
    latest?: string;
    inputs?: Input[];
  };
}

type PluginsMap = {
  [pluginKey: string]: string;
};

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

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

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

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

  return output;
}

const Plugin: React.FC<PluginProps> = ({ plugin }) => {
  const [loading, setLoading] = useState(plugin.loading);
  const finished = plugin.outputs && plugin.outputs.length > 0;
  const plugins: PluginsMap = useRecoilValue(store.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;
  }

  if (finished && loading) {
    setLoading(false);
  }

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

  return (
    <div className="flex flex-col items-start">
      <Disclosure>
        {({ open }) => {
          const iconProps: PluginIconProps = {
            className: cn(open ? 'rotate-180 transform' : '', 'h-4 w-4'),
          };
          return (
            <>
              <div
                className={cn(
                  loading ? 'bg-green-100' : 'bg-[#ECECF1]',
                  'flex items-center rounded p-3 text-sm text-gray-900',
                )}
              >
                <div>
                  <div className="flex items-center gap-3">
                    <div>{generateStatus()}</div>
                  </div>
                </div>
                {loading && <Spinner className="ml-1" />}
                <Disclosure.Button className="ml-12 flex items-center gap-2">
                  <ChevronDownIcon {...iconProps} />
                </Disclosure.Button>
              </div>

              <Disclosure.Panel className="my-3 flex max-w-full flex-col gap-3">
                <CodeBlock
                  lang={latestPlugin?.toUpperCase() || 'INPUTS'}
                  codeChildren={formatInputs(plugin.inputs ?? [])}
                  plugin={true}
                  classProp="max-h-[450px]"
                />
                {finished && (
                  <CodeBlock
                    lang="OUTPUTS"
                    codeChildren={plugin.outputs ?? ''}
                    plugin={true}
                    classProp="max-h-[450px]"
                  />
                )}
              </Disclosure.Panel>
            </>
          );
        }}
      </Disclosure>
    </div>
  );
};

export default memo(Plugin);