File size: 5,270 Bytes
cfaaa6c
 
 
 
 
1dd9186
cfaaa6c
 
 
 
 
 
1dd9186
cfaaa6c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1dd9186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cfaaa6c
 
 
 
 
 
 
 
1dd9186
cfaaa6c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
148
149
150
151
import { useEffect, useRef } from 'react';

export default function SettingsDialog({
  backendUrl,
  defaultBackendUrl,
  liveDebugUrl,
  llmProvider,
  deepinfraApiKey,
  deepinfraHasKey,
  deepinfraKeyStatus,
  isOpen,
  onBackendUrlChange,
  onLiveDebugUrlChange,
  onLlmProviderChange,
  onDeepinfraApiKeyChange,
  onClose,
  onResetToDefault,
  onSave,
}) {
  const inputRef = useRef(null);

  useEffect(() => {
    if (!isOpen || !inputRef.current) {
      return;
    }

    inputRef.current.focus();
    inputRef.current.select();
  }, [isOpen]);

  if (!isOpen) {
    return null;
  }

  return (
    <div
      className="settings-overlay"
      onMouseDown={(event) => {
        if (event.target === event.currentTarget) {
          onClose();
        }
      }}
    >
      <div className="settings-dialog">
        <div className="settings-dialog__header">
          <div>
            <div className="settings-dialog__eyebrow">Настройки</div>
            <h2 className="settings-dialog__title">Настройки графа</h2>
          </div>
          <button type="button" className="toolbar__button" onClick={onClose}>
            Закрыть
          </button>
        </div>

        <div className="settings-dialog__body">
          <label className="field-stack">
            <span className="field-label">Backend URL</span>
            <input
              ref={inputRef}
              className="node-input"
              type="text"
              value={backendUrl}
              placeholder="http://localhost:8000"
              onChange={(event) => onBackendUrlChange(event.target.value)}
            />
          </label>

          <div className="settings-dialog__note">
            Укажи адрес backend сервера, на который уходят запросы графа. Можно использовать локальный адрес вроде
            `http://localhost:8000` или удалённый сервер.
          </div>

          <div className="settings-dialog__default">
            <span>Значение из config:</span>
            <code>{defaultBackendUrl}</code>
          </div>

          <label className="field-stack">
            <span className="field-label">Live debug runtime URL</span>
            <input
              className="node-input"
              type="text"
              value={liveDebugUrl}
              placeholder="http://localhost:8001"
              onChange={(event) => onLiveDebugUrlChange(event.target.value)}
            />
          </label>

          <div className="settings-dialog__note">
            Отдельный адрес runtime для подключения к рабочему Brains. Пустое значение означает стандартный Brains URL: `http://localhost:8001`.
          </div>

          <label className="field-stack">
            <span className="field-label">LLM provider</span>
            <select
              className="node-input"
              value={llmProvider}
              onChange={(event) => onLlmProviderChange(event.target.value)}
            >
              <option value="deepinfra">DeepInfra</option>
              <option value="ollama">Ollama</option>
            </select>
          </label>

          <div className="settings-dialog__note">
            Provider применяется ко всем LLM-вызовам графа: semantic branch, save memory, knowledge answer,
            LLM-ноды ассистента, автоответ и evaluator в LLM-тесте.
          </div>

          {llmProvider === 'deepinfra' ? (
            <>
              <label className="field-stack">
                <span className="field-label">DeepInfra API Key</span>
                <input
                  className="node-input"
                  type="password"
                  value={deepinfraApiKey}
                  placeholder={deepinfraHasKey ? 'Ключ сохранен. Оставьте пустым, чтобы не менять.' : 'Введите DeepInfra API key'}
                  autoComplete="off"
                  onChange={(event) => onDeepinfraApiKeyChange(event.target.value)}
                />
              </label>

              <div className="settings-dialog__note">
                {deepinfraKeyStatus ||
                  (deepinfraHasKey
                    ? 'DeepInfra key уже сохранен локально на backend.'
                    : 'DeepInfra key обязателен и будет сохранен локально на backend.')}
              </div>
            </>
          ) : null}
        </div>

        <div className="settings-dialog__footer">
          <button type="button" className="toolbar__button" onClick={onResetToDefault}>
            Взять из config
          </button>
          <div className="button-row">
            <button type="button" className="toolbar__button" onClick={onClose}>
              Отмена
            </button>
            <button type="button" className="toolbar__button toolbar__button--primary" onClick={onSave}>
              Сохранить настройки
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}