neuro-simulator 0.5.4__py3-none-any.whl → 0.6.0__py3-none-any.whl
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.
- neuro_simulator/agent/llm.py +23 -19
- neuro_simulator/chatbot/core.py +10 -10
- neuro_simulator/chatbot/llm.py +22 -19
- neuro_simulator/chatbot/nickname_gen/generator.py +3 -3
- neuro_simulator/chatbot/tools/manager.py +10 -8
- neuro_simulator/cli.py +7 -12
- neuro_simulator/core/agent_factory.py +9 -18
- neuro_simulator/core/application.py +59 -56
- neuro_simulator/core/config.py +88 -301
- neuro_simulator/core/path_manager.py +7 -7
- neuro_simulator/dashboard/assets/{AgentView-C6qW7TIe.js → AgentView-DBq2msN_.js} +2 -2
- neuro_simulator/dashboard/assets/{ChatBotView-BRYIM_8s.js → ChatBotView-BqQsuJUv.js} +2 -2
- neuro_simulator/dashboard/assets/ConfigView-CPYMgl_d.js +2 -0
- neuro_simulator/dashboard/assets/ConfigView-aFribfyR.css +1 -0
- neuro_simulator/dashboard/assets/{ContextTab-GRHICOS3.js → ContextTab-BSROkcd2.js} +1 -1
- neuro_simulator/dashboard/assets/{ControlView-D5vPB_OE.js → ControlView-BvflkxO-.js} +1 -1
- neuro_simulator/dashboard/assets/FieldRenderer-DyPAEyOT.js +1 -0
- neuro_simulator/dashboard/assets/LogsTab-C-SZhHdN.js +1 -0
- neuro_simulator/dashboard/assets/LogsView-82wOs2Pp.js +1 -0
- neuro_simulator/dashboard/assets/{MemoryTab-BSUWFbcV.js → MemoryTab-p3Q-Wa4e.js} +3 -3
- neuro_simulator/dashboard/assets/{ToolsTab-Bjcm3fFL.js → ToolsTab-BxbFZhXs.js} +1 -1
- neuro_simulator/dashboard/assets/index-Ba5ZG3QB.js +52 -0
- neuro_simulator/dashboard/assets/{index-C7dox9UB.css → index-CcYt9OR6.css} +1 -1
- neuro_simulator/dashboard/index.html +2 -2
- neuro_simulator/services/audio.py +55 -47
- neuro_simulator/services/builtin.py +3 -0
- neuro_simulator/services/stream.py +1 -1
- neuro_simulator/utils/queue.py +2 -2
- {neuro_simulator-0.5.4.dist-info → neuro_simulator-0.6.0.dist-info}/METADATA +1 -2
- {neuro_simulator-0.5.4.dist-info → neuro_simulator-0.6.0.dist-info}/RECORD +34 -35
- requirements.txt +1 -1
- neuro_simulator/config.yaml.example +0 -117
- neuro_simulator/dashboard/assets/ConfigView-Cw-VPFzt.js +0 -2
- neuro_simulator/dashboard/assets/FieldRenderer-DaTYxmtO.js +0 -1
- neuro_simulator/dashboard/assets/LogsTab-CATao-mZ.js +0 -1
- neuro_simulator/dashboard/assets/LogsView-BM419A5R.js +0 -1
- neuro_simulator/dashboard/assets/index-BiAhe8fO.js +0 -34
- neuro_simulator/services/letta.py +0 -254
- {neuro_simulator-0.5.4.dist-info → neuro_simulator-0.6.0.dist-info}/WHEEL +0 -0
- {neuro_simulator-0.5.4.dist-info → neuro_simulator-0.6.0.dist-info}/entry_points.txt +0 -0
- {neuro_simulator-0.5.4.dist-info → neuro_simulator-0.6.0.dist-info}/licenses/LICENSE +0 -0
neuro_simulator/core/config.py
CHANGED
@@ -1,326 +1,113 @@
|
|
1
|
-
|
2
|
-
import
|
3
|
-
import sys
|
4
|
-
from pathlib import Path
|
1
|
+
|
2
|
+
import uuid
|
5
3
|
import yaml
|
6
|
-
from pydantic import BaseModel, Field
|
7
|
-
from typing import Dict, Optional, List
|
8
|
-
import logging
|
9
4
|
import asyncio
|
10
|
-
from
|
11
|
-
|
12
|
-
# 配置日志记录器
|
13
|
-
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
14
|
-
|
15
|
-
# --- 1. 定义配置的结构 (Schema) ---
|
16
|
-
|
17
|
-
class ApiKeysSettings(BaseModel):
|
18
|
-
letta_token: Optional[str] = None
|
19
|
-
letta_base_url: Optional[str] = None
|
20
|
-
neuro_agent_id: Optional[str] = None
|
21
|
-
gemini_api_key: Optional[str] = None
|
22
|
-
openai_api_key: Optional[str] = None
|
23
|
-
openai_api_base_url: Optional[str] = None
|
24
|
-
azure_speech_key: Optional[str] = None
|
25
|
-
azure_speech_region: Optional[str] = None
|
26
|
-
|
27
|
-
class StreamMetadataSettings(BaseModel):
|
28
|
-
streamer_nickname: str
|
29
|
-
stream_title: str
|
30
|
-
stream_category: str
|
31
|
-
stream_tags: List[str] = Field(default_factory=list)
|
32
|
-
|
33
|
-
class AgentSettings(BaseModel):
|
34
|
-
"""Settings for the built-in agent"""
|
35
|
-
agent_provider: str
|
36
|
-
agent_model: str
|
37
|
-
|
38
|
-
class NeuroBehaviorSettings(BaseModel):
|
39
|
-
input_chat_sample_size: int
|
40
|
-
post_speech_cooldown_sec: float
|
41
|
-
initial_greeting: str
|
42
|
-
|
5
|
+
from typing import List, Optional, Literal
|
6
|
+
from pydantic import BaseModel, Field
|
43
7
|
|
8
|
+
# --- Provider Models ---
|
9
|
+
|
10
|
+
class LLMProviderSettings(BaseModel):
|
11
|
+
"""Settings for a single LLM provider."""
|
12
|
+
provider_id: str = Field(title="Provider ID")
|
13
|
+
display_name: str = Field(title="Display Name")
|
14
|
+
provider_type: Literal["openai", "gemini"] = Field(title="Provider Type")
|
15
|
+
api_key: Optional[str] = Field(None, title="API Key")
|
16
|
+
base_url: Optional[str] = Field(None, title="Base URL")
|
17
|
+
model_name: str = Field(title="Model Name")
|
18
|
+
|
19
|
+
class TTSProviderSettings(BaseModel):
|
20
|
+
"""Settings for a single Text-to-Speech (TTS) provider."""
|
21
|
+
provider_id: str = Field(title="Provider ID")
|
22
|
+
display_name: str = Field(title="Display Name")
|
23
|
+
provider_type: Literal["azure"] = Field(title="Provider Type")
|
24
|
+
api_key: Optional[str] = Field(None, title="API Key")
|
25
|
+
region: Optional[str] = Field(None, title="Region")
|
26
|
+
|
27
|
+
# --- Core Application Settings Models ---
|
28
|
+
|
29
|
+
class NeuroSettings(BaseModel):
|
30
|
+
"""Settings for the main agent (Neuro)."""
|
31
|
+
llm_provider_id: Optional[str] = Field(None, title="LLM Provider ID")
|
32
|
+
tts_provider_id: Optional[str] = Field(None, title="TTS Provider ID")
|
33
|
+
input_chat_sample_size: int = Field(title="Input Chat Sample Size")
|
34
|
+
post_speech_cooldown_sec: float = Field(title="Post-Speech Cooldown (sec)")
|
35
|
+
initial_greeting: str = Field(title="Initial Greeting", format="text-area")
|
36
|
+
neuro_input_queue_max_size: int = Field(title="Neuro Input Queue Max Size")
|
44
37
|
|
45
|
-
class
|
46
|
-
|
47
|
-
|
38
|
+
class NicknameGenerationSettings(BaseModel):
|
39
|
+
enable_dynamic_pool: bool = Field(title="Enable Dynamic Pool")
|
40
|
+
dynamic_pool_size: int = Field(title="Dynamic Pool Size")
|
41
|
+
|
42
|
+
class ChatbotSettings(BaseModel):
|
43
|
+
"""Settings for the audience chatbot."""
|
44
|
+
llm_provider_id: Optional[str] = Field(None, title="LLM Provider ID")
|
45
|
+
generation_interval_sec: int = Field(title="Generation Interval (sec)")
|
46
|
+
chats_per_batch: int = Field(title="Chats per Batch")
|
47
|
+
nickname_generation: NicknameGenerationSettings
|
48
48
|
|
49
|
-
class
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
class StreamSettings(BaseModel):
|
50
|
+
"""Settings related to the stream's appearance."""
|
51
|
+
streamer_nickname: str = Field(title="Streamer Nickname")
|
52
|
+
stream_title: str = Field(title="Stream Title")
|
53
|
+
stream_category: str = Field(title="Stream Category")
|
54
|
+
stream_tags: List[str] = Field(title="Stream Tags")
|
53
55
|
|
54
56
|
class ServerSettings(BaseModel):
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
panel_password: Optional[str] = None
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
dynamic_pool_size: int
|
63
|
-
|
64
|
-
class ChatbotAgentSettings(BaseModel):
|
65
|
-
"""Settings for the new chatbot agent"""
|
66
|
-
agent_provider: str
|
67
|
-
agent_model: str
|
68
|
-
generation_interval_sec: int
|
69
|
-
chats_per_batch: int
|
70
|
-
nickname_generation: NicknameGenerationSettings
|
57
|
+
"""Settings for the web server and performance."""
|
58
|
+
host: str = Field(title="Host")
|
59
|
+
port: int = Field(title="Port")
|
60
|
+
panel_password: Optional[str] = Field(None, title="Panel Password", format="password")
|
61
|
+
client_origins: List[str] = Field(title="Client Origins")
|
62
|
+
audience_chat_buffer_max_size: int = Field(title="Audience Chat Buffer Max Size")
|
63
|
+
initial_chat_backlog_limit: int = Field(title="Initial Chat Backlog Limit")
|
71
64
|
|
72
65
|
class AppSettings(BaseModel):
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
performance: PerformanceSettings
|
81
|
-
server: ServerSettings
|
66
|
+
"""Root model for all application settings."""
|
67
|
+
llm_providers: List[LLMProviderSettings] = Field(title="LLM Providers")
|
68
|
+
tts_providers: List[TTSProviderSettings] = Field(title="TTS Providers")
|
69
|
+
neuro: NeuroSettings = Field(title="Neuro")
|
70
|
+
chatbot: ChatbotSettings = Field(title="Chatbot")
|
71
|
+
stream: StreamSettings = Field(title="Stream")
|
72
|
+
server: ServerSettings = Field(title="Server")
|
82
73
|
|
83
|
-
# ---
|
84
|
-
|
85
|
-
def _deep_update(source: dict, overrides: dict) -> dict:
|
86
|
-
"""
|
87
|
-
Recursively update a dictionary.
|
88
|
-
"""
|
89
|
-
for key, value in overrides.items():
|
90
|
-
if isinstance(value, Mapping) and value:
|
91
|
-
returned = _deep_update(source.get(key, {}), value)
|
92
|
-
source[key] = returned
|
93
|
-
else:
|
94
|
-
source[key] = overrides[key]
|
95
|
-
return source
|
74
|
+
# --- Configuration Manager ---
|
96
75
|
|
97
76
|
class ConfigManager:
|
98
|
-
|
99
|
-
|
100
|
-
def __new__(cls):
|
101
|
-
if cls._instance is None:
|
102
|
-
cls._instance = super(ConfigManager, cls).__new__(cls)
|
103
|
-
cls._instance._initialized = False
|
104
|
-
return cls._instance
|
105
|
-
|
77
|
+
"""Manages loading, saving, and updating the application settings."""
|
106
78
|
def __init__(self):
|
107
|
-
|
108
|
-
return
|
79
|
+
self.file_path: Optional[str] = None
|
109
80
|
self.settings: Optional[AppSettings] = None
|
110
|
-
self.
|
111
|
-
self._initialized = True
|
112
|
-
|
113
|
-
def load(self, config_path_str: str):
|
114
|
-
"""
|
115
|
-
Loads the configuration from the given path, validates it, and sets it
|
116
|
-
on the manager instance.
|
117
|
-
|
118
|
-
Raises:
|
119
|
-
FileNotFoundError: If the config file does not exist.
|
120
|
-
ValueError: If the config file is empty.
|
121
|
-
pydantic.ValidationError: If the config file content does not match the AppSettings schema.
|
122
|
-
"""
|
123
|
-
config_path = Path(config_path_str)
|
81
|
+
self.update_callbacks = []
|
124
82
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
if yaml_config is None:
|
131
|
-
raise ValueError(f"Configuration file '{config_path}' is empty.")
|
132
|
-
|
133
|
-
# This will raise ValidationError on failure
|
134
|
-
self.settings = AppSettings.model_validate(yaml_config)
|
135
|
-
logging.info("Configuration loaded and validated successfully.")
|
83
|
+
def load(self, file_path: str):
|
84
|
+
self.file_path = file_path
|
85
|
+
with open(self.file_path, 'r') as f:
|
86
|
+
data = yaml.safe_load(f)
|
87
|
+
self.settings = AppSettings.model_validate(data)
|
136
88
|
|
137
89
|
def save_settings(self):
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
try:
|
143
|
-
# 1. Read the existing config file as text to preserve comments and formatting
|
144
|
-
with open(config_file_path, 'r', encoding='utf-8') as f:
|
145
|
-
config_lines = f.readlines()
|
146
|
-
|
147
|
-
# 2. Get the current settings from memory
|
148
|
-
config_to_save = self.settings.model_dump(mode='json', exclude={'api_keys'})
|
90
|
+
if self.settings and self.file_path:
|
91
|
+
with open(self.file_path, 'w') as f:
|
92
|
+
yaml.dump(self.settings.model_dump(exclude_none=True), f, sort_keys=False)
|
149
93
|
|
150
|
-
|
151
|
-
|
152
|
-
existing_config = yaml.safe_load(f)
|
153
|
-
if 'api_keys' in existing_config:
|
154
|
-
# 4. Add the preserved api_keys block back to the data to be saved.
|
155
|
-
config_to_save['api_keys'] = existing_config['api_keys']
|
94
|
+
def get_settings_schema(self):
|
95
|
+
return AppSettings.model_json_schema()
|
156
96
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
with open(config_file_path, 'w', encoding='utf-8') as f:
|
162
|
-
f.writelines(updated_lines)
|
163
|
-
|
164
|
-
logging.info(f"Configuration saved to {config_file_path}")
|
165
|
-
except Exception as e:
|
166
|
-
logging.error(f"Failed to save configuration to {config_file_path}: {e}")
|
167
|
-
|
168
|
-
def _update_config_lines(self, lines, config_data):
|
169
|
-
"""Updates config lines with new values while preserving comments and formatting."""
|
170
|
-
updated_lines = []
|
171
|
-
i = 0
|
172
|
-
while i < len(lines):
|
173
|
-
line = lines[i]
|
174
|
-
stripped_line = line.strip()
|
175
|
-
|
176
|
-
# Skip empty lines and comments
|
177
|
-
if not stripped_line or stripped_line.startswith('#'):
|
178
|
-
updated_lines.append(line)
|
179
|
-
i += 1
|
180
|
-
continue
|
181
|
-
|
182
|
-
# Check if this line is a top-level key
|
183
|
-
if ':' in stripped_line and not stripped_line.startswith(' ') and not stripped_line.startswith('\t'):
|
184
|
-
key = stripped_line.split(':')[0].strip()
|
185
|
-
if key in config_data:
|
186
|
-
value = config_data[key]
|
187
|
-
if isinstance(value, dict):
|
188
|
-
# Handle nested dictionaries
|
189
|
-
updated_lines.append(line)
|
190
|
-
i += 1
|
191
|
-
# Process nested items
|
192
|
-
i = self._update_nested_config_lines(lines, updated_lines, i, value, 1)
|
193
|
-
else:
|
194
|
-
# Handle simple values
|
195
|
-
indent = len(line) - len(line.lstrip())
|
196
|
-
if isinstance(value, str) and '\n' in value:
|
197
|
-
# Handle multiline strings
|
198
|
-
updated_lines.append(' ' * indent + f"{key}: |\n")
|
199
|
-
for subline in value.split('\n'):
|
200
|
-
updated_lines.append(' ' * (indent + 2) + subline + '\n')
|
201
|
-
elif isinstance(value, list):
|
202
|
-
# Handle lists
|
203
|
-
updated_lines.append(' ' * indent + f"{key}:\n")
|
204
|
-
for item in value:
|
205
|
-
updated_lines.append(' ' * (indent + 2) + f"- {item}\n")
|
206
|
-
else:
|
207
|
-
# Handle simple values
|
208
|
-
updated_lines.append(' ' * indent + f"{key}: {value}\n")
|
209
|
-
i += 1
|
210
|
-
else:
|
211
|
-
updated_lines.append(line)
|
212
|
-
i += 1
|
213
|
-
else:
|
214
|
-
updated_lines.append(line)
|
215
|
-
i += 1
|
216
|
-
|
217
|
-
return updated_lines
|
218
|
-
|
219
|
-
def _update_nested_config_lines(self, lines, updated_lines, start_index, config_data, depth):
|
220
|
-
"""Recursively updates nested config lines."""
|
221
|
-
i = start_index
|
222
|
-
indent_size = depth * 2
|
223
|
-
|
224
|
-
while i < len(lines):
|
225
|
-
line = lines[i]
|
226
|
-
stripped_line = line.strip()
|
227
|
-
|
228
|
-
# Check indentation level
|
229
|
-
current_indent = len(line) - len(line.lstrip())
|
230
|
-
|
231
|
-
# If we've moved to a less indented section, we're done with this nested block
|
232
|
-
if current_indent < indent_size:
|
233
|
-
break
|
234
|
-
|
235
|
-
# Skip empty lines and comments
|
236
|
-
if not stripped_line or stripped_line.startswith('#'):
|
237
|
-
updated_lines.append(line)
|
238
|
-
i += 1
|
239
|
-
continue
|
97
|
+
async def update_settings(self, updated_data: dict):
|
98
|
+
if self.settings:
|
99
|
+
updated_model_dict = self.settings.model_dump()
|
100
|
+
updated_model_dict.update(updated_data)
|
240
101
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
if
|
245
|
-
|
246
|
-
if isinstance(value, dict):
|
247
|
-
# Handle nested dictionaries
|
248
|
-
updated_lines.append(line)
|
249
|
-
i += 1
|
250
|
-
i = self._update_nested_config_lines(lines, updated_lines, i, value, depth + 1)
|
251
|
-
else:
|
252
|
-
# Handle simple values
|
253
|
-
if isinstance(value, str) and '\n' in value:
|
254
|
-
# Handle multiline strings
|
255
|
-
updated_lines.append(' ' * indent_size + f"{key}: |\n")
|
256
|
-
for subline in value.split('\n'):
|
257
|
-
updated_lines.append(' ' * (indent_size + 2) + subline + '\n')
|
258
|
-
i += 1
|
259
|
-
elif isinstance(value, list):
|
260
|
-
# Handle lists
|
261
|
-
updated_lines.append(' ' * indent_size + f"{key}:\n")
|
262
|
-
for item in value:
|
263
|
-
updated_lines.append(' ' * (indent_size + 2) + f"- {item}\n")
|
264
|
-
i += 1
|
265
|
-
else:
|
266
|
-
# Handle simple values
|
267
|
-
updated_lines.append(' ' * indent_size + f"{key}: {value}\n")
|
268
|
-
i += 1
|
102
|
+
self.settings = AppSettings.model_validate(updated_model_dict)
|
103
|
+
self.save_settings()
|
104
|
+
for callback in self.update_callbacks:
|
105
|
+
if asyncio.iscoroutinefunction(callback):
|
106
|
+
await callback(self.settings)
|
269
107
|
else:
|
270
|
-
|
271
|
-
i += 1
|
272
|
-
else:
|
273
|
-
updated_lines.append(line)
|
274
|
-
i += 1
|
275
|
-
|
276
|
-
return i
|
108
|
+
callback(self.settings)
|
277
109
|
|
278
110
|
def register_update_callback(self, callback):
|
279
|
-
|
280
|
-
self._update_callbacks.append(callback)
|
281
|
-
|
282
|
-
async def update_settings(self, new_settings_data: dict):
|
283
|
-
"""
|
284
|
-
Updates the settings by merging new data, re-validating the entire
|
285
|
-
model to ensure sub-models are correctly instantiated, and then
|
286
|
-
notifying callbacks.
|
287
|
-
"""
|
288
|
-
try:
|
289
|
-
# 1. Dump the current settings model to a dictionary.
|
290
|
-
current_settings_dict = self.settings.model_dump()
|
291
|
-
|
292
|
-
# 2. Recursively update the dictionary with the new data.
|
293
|
-
updated_settings_dict = _deep_update(current_settings_dict, new_settings_data)
|
294
|
-
|
295
|
-
# 3. Re-validate the entire dictionary back into a Pydantic model.
|
296
|
-
# This is the crucial step that reconstructs the sub-models.
|
297
|
-
self.settings = AppSettings.model_validate(updated_settings_dict)
|
298
|
-
|
299
|
-
# 4. Save the updated configuration to the YAML file.
|
300
|
-
self.save_settings()
|
301
|
-
|
302
|
-
# 5. Call registered callbacks with the new, valid settings model.
|
303
|
-
for callback in self._update_callbacks:
|
304
|
-
try:
|
305
|
-
if asyncio.iscoroutinefunction(callback):
|
306
|
-
await callback(self.settings)
|
307
|
-
else:
|
308
|
-
callback(self.settings)
|
309
|
-
except Exception as e:
|
310
|
-
logging.error(f"Error executing settings update callback: {e}", exc_info=True)
|
311
|
-
|
312
|
-
logging.info("Runtime configuration updated and callbacks executed.")
|
313
|
-
except Exception as e:
|
314
|
-
logging.error(f"Failed to update settings: {e}", exc_info=True)
|
111
|
+
self.update_callbacks.append(callback)
|
315
112
|
|
316
|
-
|
317
|
-
# --- 3. 创建全局可访问的配置实例 ---
|
318
113
|
config_manager = ConfigManager()
|
319
|
-
|
320
|
-
# --- 4. 运行时更新配置的函数 (legacy wrapper for compatibility) ---
|
321
|
-
async def update_and_broadcast_settings(new_settings_data: dict):
|
322
|
-
await config_manager.update_settings(new_settings_data)
|
323
|
-
# Broadcast stream_metadata changes specifically for now
|
324
|
-
if 'stream_metadata' in new_settings_data:
|
325
|
-
from .stream_manager import live_stream_manager
|
326
|
-
await live_stream_manager.broadcast_stream_metadata()
|
@@ -31,18 +31,18 @@ class PathManager:
|
|
31
31
|
self.core_memory_path = self.shared_memories_dir / "core_memory.json"
|
32
32
|
self.temp_memory_path = self.shared_memories_dir / "temp_memory.json"
|
33
33
|
|
34
|
-
# --- Chatbot
|
34
|
+
# --- Chatbot Paths ---
|
35
35
|
self.chatbot_root_dir = self.working_dir / "chatbot"
|
36
|
-
self.
|
36
|
+
self.chatbot_dir = self.chatbot_root_dir / "chatbot"
|
37
37
|
self.chatbot_memory_agent_dir = self.chatbot_root_dir / "memory_agent"
|
38
38
|
self.chatbot_memories_dir = self.chatbot_root_dir / "memories"
|
39
39
|
self.chatbot_tools_dir = self.chatbot_root_dir / "tools"
|
40
40
|
self.chatbot_builtin_tools_dir = self.chatbot_tools_dir / "builtin_tools"
|
41
41
|
self.chatbot_nickname_data_dir = self.chatbot_root_dir / "nickname_gen" / "data"
|
42
42
|
|
43
|
-
self.
|
44
|
-
self.
|
45
|
-
self.
|
43
|
+
self.chatbot_prompt_path = self.chatbot_dir / "chatbot_prompt.txt"
|
44
|
+
self.chatbot_tools_path = self.chatbot_dir / "tools.json"
|
45
|
+
self.chatbot_history_path = self.chatbot_dir / "history.jsonl"
|
46
46
|
|
47
47
|
self.chatbot_memory_agent_prompt_path = self.chatbot_memory_agent_dir / "memory_prompt.txt"
|
48
48
|
self.chatbot_memory_agent_tools_path = self.chatbot_memory_agent_dir / "tools.json"
|
@@ -63,7 +63,7 @@ class PathManager:
|
|
63
63
|
self.user_tools_dir,
|
64
64
|
self.builtin_tools_dir,
|
65
65
|
self.chatbot_root_dir,
|
66
|
-
self.
|
66
|
+
self.chatbot_dir,
|
67
67
|
self.chatbot_memory_agent_dir,
|
68
68
|
self.chatbot_memories_dir,
|
69
69
|
self.chatbot_tools_dir,
|
@@ -87,4 +87,4 @@ def initialize_path_manager(working_dir: str):
|
|
87
87
|
global path_manager
|
88
88
|
if path_manager is None:
|
89
89
|
path_manager = PathManager(working_dir)
|
90
|
-
path_manager.initialize_directories()
|
90
|
+
path_manager.initialize_directories()
|
@@ -1,2 +1,2 @@
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ContextTab-
|
2
|
-
import{d as C,
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ContextTab-BSROkcd2.js","assets/index-Ba5ZG3QB.js","assets/index-CcYt9OR6.css","assets/ContextTab-DyPsixHQ.css","assets/MemoryTab-p3Q-Wa4e.js","assets/MemoryTab-DPthi6jg.css","assets/ToolsTab-BxbFZhXs.js","assets/LogsTab-C-SZhHdN.js","assets/LogsTab-wg3i3S6b.css"])))=>i.map(i=>d[i]);
|
2
|
+
import{d as C,j as k,k as I,l as L,n as c,z as P,e as t,g as v,w as o,b as n,f as a,h as d,q as r,s as u,o as f,_ as D}from"./index-Ba5ZG3QB.js";const N={class:"agent-view-wrapper"},O={key:0,class:"overlay"},R={class:"overlay-content"},B=C({__name:"AgentView",setup(z){const g=r(()=>u(()=>import("./ContextTab-BSROkcd2.js"),__vite__mapDeps([0,1,2,3]))),b=r(()=>u(()=>import("./MemoryTab-p3Q-Wa4e.js"),__vite__mapDeps([4,1,2,5]))),V=r(()=>u(()=>import("./ToolsTab-BxbFZhXs.js"),__vite__mapDeps([6,1,2]))),w=r(()=>u(()=>import("./LogsTab-C-SZhHdN.js"),__vite__mapDeps([7,1,2,8]))),m=k(),s=I("context"),p=L(()=>m.config?.agent_type&&m.config.agent_type!=="builtin");return(S,e)=>{const x=n("v-icon"),l=n("v-tab"),y=n("v-tabs"),_=n("v-window-item"),E=n("v-window"),T=n("v-card-text"),A=n("v-card");return f(),c("div",N,[p.value?(f(),c("div",O,[v("div",R,[t(x,{size:"x-large",class:"mb-4"},{default:o(()=>[...e[2]||(e[2]=[a("mdi-link-variant",-1)])]),_:1}),e[3]||(e[3]=v("h2",{class:"text-h5"},"当前正在调用外部 Agent",-1)),e[4]||(e[4]=v("p",{class:"text-body-1"},"请前往相应平台进行控制",-1))])])):P("",!0),t(A,{disabled:p.value},{default:o(()=>[t(y,{modelValue:s.value,"onUpdate:modelValue":e[0]||(e[0]=i=>s.value=i),"bg-color":"primary",grow:""},{default:o(()=>[t(l,{value:"context"},{default:o(()=>[...e[5]||(e[5]=[a("对话",-1)])]),_:1}),t(l,{value:"memory"},{default:o(()=>[...e[6]||(e[6]=[a("记忆",-1)])]),_:1}),t(l,{value:"tools"},{default:o(()=>[...e[7]||(e[7]=[a("工具",-1)])]),_:1}),t(l,{value:"logs"},{default:o(()=>[...e[8]||(e[8]=[a("日志",-1)])]),_:1})]),_:1},8,["modelValue"]),t(T,null,{default:o(()=>[t(E,{modelValue:s.value,"onUpdate:modelValue":e[1]||(e[1]=i=>s.value=i)},{default:o(()=>[t(_,{value:"context"},{default:o(()=>[t(d(g))]),_:1}),t(_,{value:"memory"},{default:o(()=>[t(d(b))]),_:1}),t(_,{value:"tools"},{default:o(()=>[t(d(V))]),_:1}),t(_,{value:"logs"},{default:o(()=>[t(d(w))]),_:1})]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["disabled"])])}}}),j=D(B,[["__scopeId","data-v-871d2dc1"]]);export{j as default};
|
@@ -1,2 +1,2 @@
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ContextTab-
|
2
|
-
import{d as E,
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ContextTab-BSROkcd2.js","assets/index-Ba5ZG3QB.js","assets/index-CcYt9OR6.css","assets/ContextTab-DyPsixHQ.css","assets/MemoryTab-p3Q-Wa4e.js","assets/MemoryTab-DPthi6jg.css","assets/ToolsTab-BxbFZhXs.js","assets/LogsTab-C-SZhHdN.js","assets/LogsTab-wg3i3S6b.css"])))=>i.map(i=>d[i]);
|
2
|
+
import{d as E,k as y,n as C,g as d,e as o,w as e,b as a,f as n,h as u,q as r,s as v,o as g,_ as A}from"./index-Ba5ZG3QB.js";const I={class:"chatbot-view-wrapper"},P={class:"overlay"},B={class:"overlay-content"},L=E({__name:"ChatBotView",setup(D){const i=r(()=>v(()=>import("./ContextTab-BSROkcd2.js"),__vite__mapDeps([0,1,2,3]))),p=r(()=>v(()=>import("./MemoryTab-p3Q-Wa4e.js"),__vite__mapDeps([4,1,2,5]))),f=r(()=>v(()=>import("./ToolsTab-BxbFZhXs.js"),__vite__mapDeps([6,1,2]))),c=r(()=>v(()=>import("./LogsTab-C-SZhHdN.js"),__vite__mapDeps([7,1,2,8]))),s=y("context");return(O,t)=>{const b=a("v-icon"),l=a("v-tab"),w=a("v-tabs"),_=a("v-window-item"),V=a("v-window"),x=a("v-card-text"),T=a("v-card");return g(),C("div",I,[d("div",P,[d("div",B,[o(b,{size:"x-large",class:"mb-4"},{default:e(()=>[...t[2]||(t[2]=[n("mdi-dev-to",-1)])]),_:1}),t[3]||(t[3]=d("h2",{class:"text-h5"},"Chatbot 控制开发中",-1)),t[4]||(t[4]=d("p",{class:"text-body-1"},"后端 API 尚未实现",-1))])]),o(T,null,{default:e(()=>[o(w,{modelValue:s.value,"onUpdate:modelValue":t[0]||(t[0]=m=>s.value=m),"bg-color":"primary",grow:""},{default:e(()=>[o(l,{value:"context"},{default:e(()=>[...t[5]||(t[5]=[n("对话",-1)])]),_:1}),o(l,{value:"memory"},{default:e(()=>[...t[6]||(t[6]=[n("记忆",-1)])]),_:1}),o(l,{value:"tools"},{default:e(()=>[...t[7]||(t[7]=[n("工具",-1)])]),_:1}),o(l,{value:"logs"},{default:e(()=>[...t[8]||(t[8]=[n("日志",-1)])]),_:1})]),_:1},8,["modelValue"]),o(x,null,{default:e(()=>[o(V,{modelValue:s.value,"onUpdate:modelValue":t[1]||(t[1]=m=>s.value=m)},{default:e(()=>[o(_,{value:"context"},{default:e(()=>[o(u(i))]),_:1}),o(_,{value:"memory"},{default:e(()=>[o(u(p))]),_:1}),o(_,{value:"tools"},{default:e(()=>[o(u(f))]),_:1}),o(_,{value:"logs"},{default:e(()=>[o(u(c))]),_:1})]),_:1},8,["modelValue"])]),_:1})]),_:1})])}}}),k=A(L,[["__scopeId","data-v-ed63d404"]]);export{k as default};
|
@@ -0,0 +1,2 @@
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/FieldRenderer-DyPAEyOT.js","assets/index-Ba5ZG3QB.js","assets/index-CcYt9OR6.css"])))=>i.map(i=>d[i]);
|
2
|
+
import{d as U,i as E,j as G,a as $,k as b,l as D,m as I,n as l,e as u,g as O,b as r,t as h,h as p,w as d,F as V,p as x,f as B,o as n,c as j,q as M,s as P}from"./index-Ba5ZG3QB.js";const R={key:0,class:"text-center pa-10"},T={class:"mt-4"},q={key:1},W={class:"text-h4 mb-6"},J=U({__name:"ConfigView",setup(z){const{t:_}=E(),F=M(()=>P(()=>import("./FieldRenderer-DyPAEyOT.js"),__vite__mapDeps([0,1,2]))),f=G(),S=$(),k=b(!0),m=b(null),C=b(!1),A=D(()=>{const s=f.schema;if(!s||!s.properties)return[];const c=["llm_providers","tts_providers","neuro","chatbot","stream","server"],v=Object.keys(s.properties);return v.sort((t,o)=>{const i=c.indexOf(t),a=c.indexOf(o);return i!==-1&&a!==-1?i-a:i!==-1?-1:a!==-1?1:t.localeCompare(o)}),v.map(t=>{const o=s.properties[t];if(o.$ref){const i=o.$ref.split("/").pop()||"",a=s.$defs?.[i]||{},y=a.properties||{};return{key:t,title:o.title||a.title||t.charAt(0).toUpperCase()+t.slice(1),isGroup:!0,properties:Object.keys(y).map(g=>({key:g,schema:y[g]}))}}return{key:t,title:o.title||t.charAt(0).toUpperCase()+t.slice(1),isGroup:!1,properties:[{key:t,schema:o}]}})});async function L(){if(S.isConnected){C.value=!0;try{await S.sendAdminWsMessage("update_configs",f.config),console.log("Config saved successfully!")}catch(s){console.error("Failed to save config:",s)}finally{C.value=!1}}}return I(async()=>{k.value=!0;try{await f.fetchSchema(),await f.fetchConfig()}finally{k.value=!1}}),(s,c)=>{const v=r("v-progress-circular"),t=r("v-tab"),o=r("v-tabs"),i=r("v-btn"),a=r("v-card-actions"),y=r("v-card"),g=r("v-window-item"),N=r("v-window");return n(),l("div",null,[k.value?(n(),l("div",R,[u(v,{indeterminate:"",color:"primary"}),O("p",T,h(p(_)("Loading configuration...")),1)])):(n(),l("div",q,[u(o,{modelValue:m.value,"onUpdate:modelValue":c[0]||(c[0]=e=>m.value=e),"bg-color":"primary",class:"mb-4 config-tabs",grow:""},{default:d(()=>[(n(!0),l(V,null,x(A.value,e=>(n(),j(t,{key:e.key,value:e.key},{default:d(()=>[B(h(p(_)(e.title)),1)]),_:2},1032,["value"]))),128))]),_:1},8,["modelValue"]),u(a,{class:"justify-end pa-4"},{default:d(()=>[u(i,{onClick:L,color:"primary",variant:"flat",loading:C.value},{default:d(()=>[B(h(p(_)("Save Configuration")),1)]),_:1},8,["loading"])]),_:1}),u(N,{modelValue:m.value,"onUpdate:modelValue":c[1]||(c[1]=e=>m.value=e),eager:""},{default:d(()=>[(n(!0),l(V,null,x(A.value,e=>(n(),j(g,{key:e.key,value:e.key},{default:d(()=>[u(y,{flat:"",class:"pa-4"},{default:d(()=>[O("h1",W,h(p(_)(e.title)),1),(n(!0),l(V,null,x(e.properties,w=>(n(),l("div",{key:w.key},[u(p(F),{"group-key":e.isGroup?e.key:null,"prop-key":w.key,"prop-schema":w.schema},null,8,["group-key","prop-key","prop-schema"])]))),128))]),_:2},1024)]),_:2},1032,["value"]))),128))]),_:1},8,["modelValue"])]))])}}});export{J as default};
|
@@ -0,0 +1 @@
|
|
1
|
+
.config-tabs .v-tab{text-transform:none!important}
|
@@ -1 +1 @@
|
|
1
|
-
import{d as m,
|
1
|
+
import{d as m,k as g,A as x,a as v,x as f,b as C,n as o,o as s,g as r,e as h,t as l,h as p,F as y,p as b,f as w,_ as k}from"./index-Ba5ZG3QB.js";const V={class:"d-flex align-center mb-4"},S={key:0,class:"context-prompt-view"},A={key:1,class:"context-conversation-view"},M=m({__name:"ContextTab",setup(B){const t=g(!1),n=x(),c=v();async function i(){if(c.isConnected)if(t.value)try{const e=await c.sendAdminWsMessage("get_last_prompt");n.agentContext=e.prompt}catch(e){console.error("获取最新Prompt失败:",e),n.agentContext=`获取提示词失败: ${e}`}else try{const e=await c.sendAdminWsMessage("get_agent_context");n.agentContext=e}catch(e){console.error("获取上下文失败:",e)}}return f(t,i),i(),(e,d)=>{const u=C("v-switch");return s(),o("div",null,[r("div",V,[h(u,{modelValue:t.value,"onUpdate:modelValue":d[0]||(d[0]=a=>t.value=a),label:"上下文模式",color:"primary","hide-details":""},null,8,["modelValue"])]),t.value?(s(),o("div",S,[r("pre",null,l(p(n).agentContext),1)])):(s(),o("div",A,[(s(!0),o(y,null,b(p(n).agentContext,(a,_)=>(s(),o("div",{key:_,class:"message-item"},[r("p",null,[r("strong",null,l(a.role)+":",1),w(" "+l(a.content),1)])]))),128))]))])}}}),T=k(M,[["__scopeId","data-v-dd6969bb"]]);export{T as default};
|
@@ -1 +1 @@
|
|
1
|
-
import{d as C,u as S,a as w,r as x,c as k,w as o,b as r,e as a,f as n,g as i,h as _,t as V,o as b,_ as A}from"./index-
|
1
|
+
import{d as C,u as S,a as w,r as x,c as k,w as o,b as r,e as a,f as n,g as i,h as _,t as V,o as b,_ as A}from"./index-Ba5ZG3QB.js";const B={class:"stream-status"},M={class:"control-buttons"},N=C({__name:"ControlView",setup(W){const d=S(),l=w(),e=x({start:!1,stop:!1,restart:!1});async function u(){e.start=!0;try{await l.sendAdminWsMessage("start_stream")}catch(s){console.error(s)}finally{e.start=!1}}async function f(){e.stop=!0;try{await l.sendAdminWsMessage("stop_stream")}catch(s){console.error(s)}finally{e.stop=!1}}async function p(){e.restart=!0;try{await l.sendAdminWsMessage("restart_stream")}catch(s){console.error(s)}finally{e.restart=!1}}return(s,t)=>{const m=r("v-card-title"),g=r("v-chip"),c=r("v-btn"),v=r("v-card-text"),y=r("v-card");return b(),k(y,null,{default:o(()=>[a(m,null,{default:o(()=>[...t[0]||(t[0]=[n("直播控制",-1)])]),_:1}),a(v,null,{default:o(()=>[i("div",B,[i("p",null,[t[1]||(t[1]=n("当前状态: ",-1)),a(g,{color:_(d).isRunning?"green":"red",dark:""},{default:o(()=>[n(V(_(d).isRunning?"运行中":"已停止"),1)]),_:1},8,["color"])])]),i("div",M,[a(c,{color:"primary",onClick:u,loading:e.start},{default:o(()=>[...t[2]||(t[2]=[n("开始直播",-1)])]),_:1},8,["loading"]),a(c,{color:"error",onClick:f,loading:e.stop},{default:o(()=>[...t[3]||(t[3]=[n("停止直播",-1)])]),_:1},8,["loading"]),a(c,{color:"warning",onClick:p,loading:e.restart},{default:o(()=>[...t[4]||(t[4]=[n("重启直播",-1)])]),_:1},8,["loading"])])]),_:1})]),_:1})}}}),D=A(N,[["__scopeId","data-v-607a7661"]]);export{D as default};
|
@@ -0,0 +1 @@
|
|
1
|
+
import{d as ee,i as te,j as le,l as U,k as C,r as ne,b as p,n as b,o as d,c as m,z as S,h as r,e as s,F as T,p as J,w as v,g as P,t as f,f as N,q as oe,s as ae}from"./index-Ba5ZG3QB.js";let O;const ie=new Uint8Array(16);function re(){if(!O&&(O=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!O))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return O(ie)}const u=[];for(let e=0;e<256;++e)u.push((e+256).toString(16).slice(1));function de(e,t=0){return u[e[t+0]]+u[e[t+1]]+u[e[t+2]]+u[e[t+3]]+"-"+u[e[t+4]]+u[e[t+5]]+"-"+u[e[t+6]]+u[e[t+7]]+"-"+u[e[t+8]]+u[e[t+9]]+"-"+u[e[t+10]]+u[e[t+11]]+u[e[t+12]]+u[e[t+13]]+u[e[t+14]]+u[e[t+15]]}const ue=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),B={randomUUID:ue};function pe(e,t,j){if(B.randomUUID&&!e)return B.randomUUID();e=e||{};const l=e.random||(e.rng||re)();return l[6]=l[6]&15|64,l[8]=l[8]&63|128,de(l)}const se={class:"mb-6"},ce={key:8},me={key:0,class:"text-body-2"},ve={key:1,class:"text-body-2"},ye=ee({__name:"FieldRenderer",props:{groupKey:{},propKey:{},propSchema:{},isInDialog:{type:Boolean},dialogData:{}},setup(e){const{t}=te(),j=oe(()=>ae(()=>Promise.resolve().then(()=>fe),void 0)),l=e,y=le();function h(i){return l.propSchema.type===i?!0:Array.isArray(l.propSchema.anyOf)?l.propSchema.anyOf.some(o=>o.type===i):!1}const $=U(()=>!h("array")||!l.propSchema.items?!1:l.propSchema.items.type==="object"||!!l.propSchema.items.$ref),V=U(()=>{if(!$.value)return{};const i=l.propSchema.items;if(i.$ref){const o=i.$ref.split("/").pop();return y.schema.$defs?.[o]||{}}return i}),w=U(()=>l.propKey.endsWith("_provider_id")),F=U(()=>l.propKey==="llm_provider_id"?y.config.llm_providers||[]:l.propKey==="tts_provider_id"?y.config.tts_providers||[]:[]),a=U({get(){return l.isInDialog?l.dialogData?.[l.propKey]:l.groupKey?y.config[l.groupKey]?.[l.propKey]:y.config[l.propKey]},set(i){if(l.isInDialog){l.dialogData&&(l.dialogData[l.propKey]=i);return}l.groupKey?(y.config[l.groupKey]||(y.config[l.groupKey]={}),y.config[l.groupKey][l.propKey]=i):y.config[l.propKey]=i}}),k=C(!1),I=C(!1),c=ne({}),_=C(-1);function z(){I.value=!1,Object.keys(c).forEach(K=>delete c[K]);const i=V.value.properties||{};for(const K in i)c[K]=i[K].default??null;const o=c.provider_type||V.value.properties?.provider_type?.enum?.[0]||"unknown",g=l.propKey==="llm_providers"?"llm":"tts";c.provider_id=`${g}-${o}-${pe()}`,k.value=!0}function M(i,o){I.value=!0,_.value=o,Object.keys(c).forEach(g=>delete c[g]),Object.assign(c,JSON.parse(JSON.stringify(i))),k.value=!0}function L(){const i=a.value||[];I.value?i[_.value]=JSON.parse(JSON.stringify(c)):i.push(JSON.parse(JSON.stringify(c))),a.value=i,k.value=!1}function q(i){const o=a.value||[];o.splice(i,1),a.value=o}return(i,o)=>{const g=p("v-text-field"),K=p("v-textarea"),H=p("v-switch"),A=p("v-select"),x=p("v-btn"),W=p("v-card-title"),E=p("v-card-text"),R=p("v-card"),G=p("v-spacer"),Q=p("v-card-actions"),X=p("v-dialog"),Y=p("v-combobox");return d(),b("div",se,[e.propKey==="provider_id"?(d(),m(g,{key:0,modelValue:a.value,"onUpdate:modelValue":o[0]||(o[0]=n=>a.value=n),label:r(t)(e.propSchema.title||e.propKey),hint:e.propSchema.description,"persistent-hint":"",variant:"outlined",density:"compact",disabled:""},null,8,["modelValue","label","hint"])):h("integer")||h("number")?(d(),m(g,{key:1,modelValue:a.value,"onUpdate:modelValue":o[1]||(o[1]=n=>a.value=n),modelModifiers:{number:!0},label:r(t)(e.propSchema.title||e.propKey),hint:e.propSchema.description,type:"number","persistent-hint":"",variant:"outlined",density:"compact"},null,8,["modelValue","label","hint"])):h("string")&&e.propSchema.format==="password"?(d(),m(g,{key:2,modelValue:a.value,"onUpdate:modelValue":o[2]||(o[2]=n=>a.value=n),label:r(t)(e.propSchema.title||e.propKey),hint:e.propSchema.description,type:"password","persistent-hint":"",variant:"outlined",density:"compact"},null,8,["modelValue","label","hint"])):h("string")&&e.propSchema.format==="text-area"?(d(),m(K,{key:3,modelValue:a.value,"onUpdate:modelValue":o[3]||(o[3]=n=>a.value=n),label:r(t)(e.propSchema.title||e.propKey),hint:e.propSchema.description,"persistent-hint":"",variant:"outlined"},null,8,["modelValue","label","hint"])):h("string")&&!e.propSchema.enum&&!w.value?(d(),m(g,{key:4,modelValue:a.value,"onUpdate:modelValue":o[4]||(o[4]=n=>a.value=n),label:r(t)(e.propSchema.title||e.propKey),hint:e.propSchema.description,"persistent-hint":"",variant:"outlined",density:"compact"},null,8,["modelValue","label","hint"])):S("",!0),h("boolean")?(d(),m(H,{key:5,modelValue:a.value,"onUpdate:modelValue":o[5]||(o[5]=n=>a.value=n),label:r(t)(e.propSchema.title||e.propKey),hint:e.propSchema.description,"persistent-hint":"",color:"primary",inset:""},null,8,["modelValue","label","hint"])):S("",!0),e.propSchema.enum?(d(),m(A,{key:6,modelValue:a.value,"onUpdate:modelValue":o[6]||(o[6]=n=>a.value=n),items:e.propSchema.enum,label:r(t)(e.propSchema.title||e.propKey),hint:e.propSchema.description,"persistent-hint":"",variant:"outlined",density:"compact"},null,8,["modelValue","items","label","hint"])):S("",!0),w.value?(d(),m(A,{key:7,modelValue:a.value,"onUpdate:modelValue":o[7]||(o[7]=n=>a.value=n),items:F.value,"item-title":"display_name","item-value":"provider_id",label:r(t)(e.propSchema.title||e.propKey),hint:e.propSchema.description,"persistent-hint":"",variant:"outlined",density:"compact",clearable:""},null,8,["modelValue","items","label","hint"])):$.value?(d(),b("div",ce,[(d(!0),b(T,null,J(a.value,(n,D)=>(d(),m(R,{key:n.provider_id||D,class:"mb-4",variant:"outlined"},{default:v(()=>[s(W,{class:"d-flex justify-space-between align-center text-body-1"},{default:v(()=>[P("span",null,f(n.display_name||r(t)("Item")+" "+(D+1)),1),P("div",null,[s(x,{icon:"mdi-pencil",size:"small",variant:"text",onClick:Z=>M(n,D)},null,8,["onClick"]),s(x,{icon:"mdi-delete",size:"small",variant:"text",onClick:Z=>q(D)},null,8,["onClick"])])]),_:2},1024),n.provider_type||n.model_name?(d(),m(E,{key:0},{default:v(()=>[n.provider_type?(d(),b("p",me,f(r(t)("Provider Type"))+": "+f(n.provider_type),1)):S("",!0),n.model_name?(d(),b("p",ve,f(r(t)("Model Name"))+": "+f(n.model_name),1)):S("",!0)]),_:2},1024)):S("",!0)]),_:2},1024))),128)),s(x,{color:"primary",onClick:z,block:""},{default:v(()=>[N(f(r(t)("Add"))+" "+f(r(t)(V.value.title||"Item")),1)]),_:1}),s(X,{modelValue:k.value,"onUpdate:modelValue":o[9]||(o[9]=n=>k.value=n),"max-width":"800px",persistent:""},{default:v(()=>[s(R,{title:r(t)(I.value?"Edit":"Add")+" "+r(t)(V.value.title||"Item")},{default:v(()=>[s(E,null,{default:v(()=>[(d(!0),b(T,null,J(Object.keys(V.value.properties||{}),n=>(d(),b("div",{key:n},[s(r(j),{"group-key":null,"prop-key":n,"prop-schema":V.value.properties[n],"is-in-dialog":!0,"dialog-data":c},null,8,["prop-key","prop-schema","dialog-data"])]))),128))]),_:1}),s(Q,null,{default:v(()=>[s(G),s(x,{text:"",onClick:o[8]||(o[8]=n=>k.value=!1)},{default:v(()=>[N(f(r(t)("Cancel")),1)]),_:1}),s(x,{color:"primary",onClick:L},{default:v(()=>[N(f(r(t)("Save")),1)]),_:1})]),_:1})]),_:1},8,["title"])]),_:1},8,["modelValue"])])):h("array")?(d(),m(Y,{key:9,modelValue:a.value,"onUpdate:modelValue":o[10]||(o[10]=n=>a.value=n),label:r(t)(e.propSchema.title||e.propKey),hint:e.propSchema.description,"persistent-hint":"",chips:"",multiple:"","closable-chips":"",variant:"outlined",density:"compact"},null,8,["modelValue","label","hint"])):S("",!0)])}}}),fe=Object.freeze(Object.defineProperty({__proto__:null,default:ye},Symbol.toStringTag,{value:"Module"}));export{ye as default};
|
@@ -0,0 +1 @@
|
|
1
|
+
import{d as r,v as l,k as c,x as g,n as s,o as t,F as u,p as i,t as p,h as _,y as f,_ as d}from"./index-Ba5ZG3QB.js";const m=r({__name:"LogsTab",setup(v){const a=l(),e=c(null);return g(()=>a.agentLogs.length,async()=>{await f(),e.value&&(e.value.scrollTop=e.value.scrollHeight)},{deep:!0}),(k,y)=>(t(),s("div",{ref_key:"logsContainer",ref:e,class:"logs-output"},[(t(!0),s(u,null,i(_(a).agentLogs,(o,n)=>(t(),s("div",{key:`agent-${n}`,class:"log-entry"},p(o),1))),128))],512))}}),h=d(m,[["__scopeId","data-v-20098789"]]);export{h as default};
|
@@ -0,0 +1 @@
|
|
1
|
+
import{d as p,v,k as f,x as g,c as m,w as t,b as s,e as n,f as x,g as k,n as l,p as w,h as y,F as L,o as a,t as C,y as V,_ as h}from"./index-Ba5ZG3QB.js";const B=p({__name:"LogsView",setup(S){const o=v(),e=f(null);return g(()=>o.serverLogs.length,async()=>{await V(),e.value&&(e.value.scrollTop=e.value.scrollHeight)},{deep:!0}),(N,r)=>{const c=s("v-card-title"),_=s("v-card-text"),d=s("v-card");return a(),m(d,null,{default:t(()=>[n(c,null,{default:t(()=>[...r[0]||(r[0]=[x("Server 日志",-1)])]),_:1}),n(_,null,{default:t(()=>[k("div",{ref_key:"logsContainer",ref:e,class:"logs-output"},[(a(!0),l(L,null,w(y(o).serverLogs,(u,i)=>(a(),l("div",{key:`server-${i}`,class:"log-entry"},C(u),1))),128))],512)]),_:1})]),_:1})}}}),F=h(B,[["__scopeId","data-v-f9df559f"]]);export{F as default};
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import{d as le,
|
1
|
+
import{d as le,A as ne,a as oe,B as re,k as x,m as ae,b as i,n as f,o as s,e as t,w as l,g as v,c as V,f as d,h as k,F as U,p as F,t as C,_ as ie}from"./index-Ba5ZG3QB.js";const se={class:"d-flex mb-4"},de={key:1},ue={class:"d-flex mb-4"},me={key:1},ce={class:"d-flex mb-4"},fe={key:0},ve={key:1},pe={class:"text-h5"},_e={class:"text-h5"},ye=le({__name:"MemoryTab",setup(xe){const p=ne(),a=oe();re();const M=x(!1),y=x({role:"user",content:""}),g=x(!1),m=x({}),b=x(!1),c=x({});function O(n=null){n?m.value={...n,contentStr:n.content.join(`
|
2
2
|
`)}:m.value={title:"",description:"",contentStr:""},g.value=!0}async function G(){if(!a.isConnected)return;const n=m.value,e={title:n.title,description:n.description,content:n.contentStr.split(`
|
3
|
-
`).filter(r=>r.trim()!=="")};try{n.id?await a.sendAdminWsMessage("update_core_memory_block",{block_id:n.id,...e}):await a.sendAdminWsMessage("create_core_memory_block",e),g.value=!1}catch(r){console.error("Failed to save core memory block:",r)}}function
|
3
|
+
`).filter(r=>r.trim()!=="")};try{n.id?await a.sendAdminWsMessage("update_core_memory_block",{block_id:n.id,...e}):await a.sendAdminWsMessage("create_core_memory_block",e),g.value=!1}catch(r){console.error("Failed to save core memory block:",r)}}function z(n=null,e=null){if(n!==null){let r=e;Array.isArray(e)?r=e.join(`
|
4
4
|
`):typeof e=="object"&&(r=JSON.stringify(e,null,2)),c.value={key:n,valueStr:r,isEditing:!0}}else c.value={key:"",valueStr:"",isEditing:!1};b.value=!0}async function H(){if(!a.isConnected||!c.value.key.trim())return;const{key:n,valueStr:e}=c.value;let r=e;try{const u=e.trim();u.startsWith("{")&&u.endsWith("}")||u.startsWith("[")&&u.endsWith("]")?r=JSON.parse(u):u.includes(`
|
5
5
|
`)&&(r=u.split(`
|
6
|
-
`).filter(S=>S.trim()!==""))}catch(u){console.warn("Could not parse value as JSON or array, saving as string.",u)}try{await a.sendAdminWsMessage("update_init_memory_item",{key:n,value:r}),b.value=!1}catch(u){console.error(`Failed to save init memory item ${n}:`,u)}}async function K(){if(!(!a.isConnected||!y.value.content.trim()))try{await a.sendAdminWsMessage("add_temp_memory",y.value),M.value=!1,y.value.content=""}catch(n){console.error("Failed to add temp memory:",n)}}async function Q(n){if(a.isConnected&&confirm("确定要删除这个记忆块吗?"))try{await a.sendAdminWsMessage("delete_core_memory_block",{block_id:n})}catch(e){console.error(`Failed to delete core memory block ${n}:`,e)}}async function R(n){if(a.isConnected&&confirm(`确定要删除键 "${n}" 吗?`))try{await a.sendAdminWsMessage("delete_init_memory_key",{key:n})}catch(e){console.error(`Failed to delete init memory item ${n}:`,e)}}async function X(n){if(a.isConnected)try{await a.sendAdminWsMessage("delete_temp_memory_item",{item_id:n})}catch(e){console.error(`Failed to delete temp memory item ${n}:`,e)}}async function Y(){if(a.isConnected&&confirm("确定要清空所有临时记忆吗?"))try{await a.sendAdminWsMessage("clear_temp_memory")}catch(n){console.error("Failed to clear temp memory:",n)}}async function E(){if(a.isConnected)try{const n=await a.sendAdminWsMessage("get_init_memory");p.handleInitMemoryUpdate(n)}catch(n){console.error("Failed to refresh init memory:",n)}}async function q(){if(a.isConnected)try{const n=await a.sendAdminWsMessage("get_temp_memory");p.handleTempMemoryUpdate(n)}catch(n){console.error("Failed to refresh temp memory:",n)}}async function J(){if(a.isConnected)try{const n=await a.sendAdminWsMessage("get_core_memory_blocks");p.handleCoreMemoryUpdate(n)}catch(n){console.error("Failed to refresh core memory:",n)}}async function Z(){a.isConnected&&await Promise.all([E(),q(),J()])}return ae(()=>{Z()}),(n,e)=>{const r=i("v-btn"),u=i("v-list-item-subtitle"),S=i("v-list-item"),L=i("v-list"),T=i("v-expansion-panel-text"),I=i("v-expansion-panel"),w=i("v-card-title"),h=i("v-card-subtitle"),$=i("v-card-text"),A=i("v-card"),ee=i("v-expansion-panels"),te=i("v-select"),W=i("v-textarea"),
|
6
|
+
`).filter(S=>S.trim()!==""))}catch(u){console.warn("Could not parse value as JSON or array, saving as string.",u)}try{await a.sendAdminWsMessage("update_init_memory_item",{key:n,value:r}),b.value=!1}catch(u){console.error(`Failed to save init memory item ${n}:`,u)}}async function K(){if(!(!a.isConnected||!y.value.content.trim()))try{await a.sendAdminWsMessage("add_temp_memory",y.value),M.value=!1,y.value.content=""}catch(n){console.error("Failed to add temp memory:",n)}}async function Q(n){if(a.isConnected&&confirm("确定要删除这个记忆块吗?"))try{await a.sendAdminWsMessage("delete_core_memory_block",{block_id:n})}catch(e){console.error(`Failed to delete core memory block ${n}:`,e)}}async function R(n){if(a.isConnected&&confirm(`确定要删除键 "${n}" 吗?`))try{await a.sendAdminWsMessage("delete_init_memory_key",{key:n})}catch(e){console.error(`Failed to delete init memory item ${n}:`,e)}}async function X(n){if(a.isConnected)try{await a.sendAdminWsMessage("delete_temp_memory_item",{item_id:n})}catch(e){console.error(`Failed to delete temp memory item ${n}:`,e)}}async function Y(){if(a.isConnected&&confirm("确定要清空所有临时记忆吗?"))try{await a.sendAdminWsMessage("clear_temp_memory")}catch(n){console.error("Failed to clear temp memory:",n)}}async function E(){if(a.isConnected)try{const n=await a.sendAdminWsMessage("get_init_memory");p.handleInitMemoryUpdate(n)}catch(n){console.error("Failed to refresh init memory:",n)}}async function q(){if(a.isConnected)try{const n=await a.sendAdminWsMessage("get_temp_memory");p.handleTempMemoryUpdate(n)}catch(n){console.error("Failed to refresh temp memory:",n)}}async function J(){if(a.isConnected)try{const n=await a.sendAdminWsMessage("get_core_memory_blocks");p.handleCoreMemoryUpdate(n)}catch(n){console.error("Failed to refresh core memory:",n)}}async function Z(){a.isConnected&&await Promise.all([E(),q(),J()])}return ae(()=>{Z()}),(n,e)=>{const r=i("v-btn"),u=i("v-list-item-subtitle"),S=i("v-list-item"),L=i("v-list"),T=i("v-expansion-panel-text"),I=i("v-expansion-panel"),w=i("v-card-title"),h=i("v-card-subtitle"),$=i("v-card-text"),A=i("v-card"),ee=i("v-expansion-panels"),te=i("v-select"),W=i("v-textarea"),B=i("v-spacer"),D=i("v-card-actions"),N=i("v-dialog"),P=i("v-text-field");return s(),f("div",null,[t(ee,{variant:"inset",class:"my-4"},{default:l(()=>[t(I,{title:"初始化记忆 (Init Memory)"},{default:l(()=>[t(T,null,{default:l(()=>[v("div",se,[t(r,{onClick:E,class:"mr-2"},{default:l(()=>[...e[16]||(e[16]=[d("刷新",-1)])]),_:1}),t(r,{onClick:e[0]||(e[0]=o=>z()),color:"primary"},{default:l(()=>[...e[17]||(e[17]=[d("添加",-1)])]),_:1})]),Object.keys(k(p).initMemory).length>0?(s(),V(L,{key:0,lines:"one"},{default:l(()=>[(s(!0),f(U,null,F(k(p).initMemory,(o,_)=>(s(),V(S,{key:_,title:_},{append:l(()=>[t(r,{onClick:j=>z(_.toString(),o),icon:"mdi-pencil",size:"x-small",variant:"text"},null,8,["onClick"]),t(r,{onClick:j=>R(_.toString()),icon:"mdi-delete",size:"x-small",variant:"text",color:"error"},null,8,["onClick"])]),default:l(()=>[t(u,{class:"value-display"},{default:l(()=>[v("pre",null,C(o),1)]),_:2},1024)]),_:2},1032,["title"]))),128))]),_:1})):(s(),f("p",de,"没有初始化记忆。"))]),_:1})]),_:1}),t(I,{title:"临时记忆 (Temp Memory)"},{default:l(()=>[t(T,null,{default:l(()=>[v("div",ue,[t(r,{onClick:q,class:"mr-2"},{default:l(()=>[...e[18]||(e[18]=[d("刷新",-1)])]),_:1}),t(r,{onClick:e[1]||(e[1]=o=>M.value=!0),color:"primary",class:"mr-2"},{default:l(()=>[...e[19]||(e[19]=[d("添加",-1)])]),_:1}),t(r,{onClick:Y,color:"error"},{default:l(()=>[...e[20]||(e[20]=[d("清空",-1)])]),_:1})]),k(p).tempMemory.length>0?(s(),V(L,{key:0,lines:"one"},{default:l(()=>[(s(!0),f(U,null,F(k(p).tempMemory,o=>(s(),V(S,{key:o.id,title:`[${o.role}] ${o.content||o.text}`,subtitle:new Date(o.timestamp).toLocaleString()},{append:l(()=>[t(r,{onClick:_=>X(o.id),icon:"mdi-delete",size:"x-small",variant:"text",color:"error"},null,8,["onClick"])]),_:2},1032,["title","subtitle"]))),128))]),_:1})):(s(),f("p",me,"没有临时记忆。"))]),_:1})]),_:1}),t(I,{title:"核心记忆 (Core Memory)"},{default:l(()=>[t(T,null,{default:l(()=>[v("div",ce,[t(r,{onClick:J,class:"mr-2"},{default:l(()=>[...e[21]||(e[21]=[d("刷新",-1)])]),_:1}),t(r,{onClick:e[2]||(e[2]=o=>O()),color:"primary"},{default:l(()=>[...e[22]||(e[22]=[d("添加记忆块",-1)])]),_:1})]),Object.keys(k(p).coreMemory).length>0?(s(),f("div",fe,[(s(!0),f(U,null,F(k(p).coreMemory,o=>(s(),V(A,{key:o.id,class:"mb-4",variant:"outlined"},{default:l(()=>[t(w,{class:"d-flex justify-space-between"},{default:l(()=>[v("span",null,C(o.title),1),v("div",null,[t(r,{onClick:_=>O(o),icon:"mdi-pencil",size:"x-small",variant:"text"},null,8,["onClick"]),t(r,{onClick:_=>Q(o.id),icon:"mdi-delete",size:"x-small",variant:"text",color:"error"},null,8,["onClick"])])]),_:2},1024),t(h,null,{default:l(()=>[d(C(o.description),1)]),_:2},1024),t($,null,{default:l(()=>[v("ul",null,[(s(!0),f(U,null,F(o.content,(_,j)=>(s(),f("li",{key:j},C(_),1))),128))])]),_:2},1024)]),_:2},1024))),128))])):(s(),f("p",ve,"没有核心记忆。"))]),_:1})]),_:1})]),_:1}),t(N,{modelValue:M.value,"onUpdate:modelValue":e[6]||(e[6]=o=>M.value=o),"max-width":"500px"},{default:l(()=>[t(A,null,{default:l(()=>[t(w,null,{default:l(()=>[...e[23]||(e[23]=[v("span",{class:"text-h5"},"添加临时记忆",-1)])]),_:1}),t($,null,{default:l(()=>[t(te,{modelValue:y.value.role,"onUpdate:modelValue":e[3]||(e[3]=o=>y.value.role=o),items:["system","user","assistant"],label:"角色",required:""},null,8,["modelValue"]),t(W,{modelValue:y.value.content,"onUpdate:modelValue":e[4]||(e[4]=o=>y.value.content=o),label:"内容",required:""},null,8,["modelValue"])]),_:1}),t(D,null,{default:l(()=>[t(B),t(r,{color:"blue-darken-1",variant:"text",onClick:e[5]||(e[5]=o=>M.value=!1)},{default:l(()=>[...e[24]||(e[24]=[d("取消",-1)])]),_:1}),t(r,{color:"blue-darken-1",variant:"text",onClick:K},{default:l(()=>[...e[25]||(e[25]=[d("添加",-1)])]),_:1})]),_:1})]),_:1})]),_:1},8,["modelValue"]),t(N,{modelValue:g.value,"onUpdate:modelValue":e[11]||(e[11]=o=>g.value=o),"max-width":"600px"},{default:l(()=>[t(A,null,{default:l(()=>[t(w,null,{default:l(()=>[v("span",pe,C(m.value.id?"编辑":"添加")+"核心记忆块",1)]),_:1}),t($,null,{default:l(()=>[t(P,{modelValue:m.value.title,"onUpdate:modelValue":e[7]||(e[7]=o=>m.value.title=o),label:"标题",required:""},null,8,["modelValue"]),t(W,{modelValue:m.value.description,"onUpdate:modelValue":e[8]||(e[8]=o=>m.value.description=o),label:"描述"},null,8,["modelValue"]),t(W,{modelValue:m.value.contentStr,"onUpdate:modelValue":e[9]||(e[9]=o=>m.value.contentStr=o),label:"内容 (每行一条)"},null,8,["modelValue"])]),_:1}),t(D,null,{default:l(()=>[t(B),t(r,{color:"blue-darken-1",variant:"text",onClick:e[10]||(e[10]=o=>g.value=!1)},{default:l(()=>[...e[26]||(e[26]=[d("取消",-1)])]),_:1}),t(r,{color:"blue-darken-1",variant:"text",onClick:G},{default:l(()=>[...e[27]||(e[27]=[d("保存",-1)])]),_:1})]),_:1})]),_:1})]),_:1},8,["modelValue"]),t(N,{modelValue:b.value,"onUpdate:modelValue":e[15]||(e[15]=o=>b.value=o),"max-width":"600px"},{default:l(()=>[t(A,null,{default:l(()=>[t(w,null,{default:l(()=>[v("span",_e,C(c.value.isEditing?"编辑":"添加")+"初始化记忆项",1)]),_:1}),t($,null,{default:l(()=>[t(P,{modelValue:c.value.key,"onUpdate:modelValue":e[12]||(e[12]=o=>c.value.key=o),label:"键",disabled:c.value.isEditing,required:""},null,8,["modelValue","disabled"]),t(W,{modelValue:c.value.valueStr,"onUpdate:modelValue":e[13]||(e[13]=o=>c.value.valueStr=o),label:"值 (可以是字符串, JSON, 或换行分隔的数组)"},null,8,["modelValue"])]),_:1}),t(D,null,{default:l(()=>[t(B),t(r,{color:"blue-darken-1",variant:"text",onClick:e[14]||(e[14]=o=>b.value=!1)},{default:l(()=>[...e[28]||(e[28]=[d("取消",-1)])]),_:1}),t(r,{color:"blue-darken-1",variant:"text",onClick:H},{default:l(()=>[...e[29]||(e[29]=[d("保存",-1)])]),_:1})]),_:1})]),_:1})]),_:1},8,["modelValue"])])}}}),Ce=ie(ye,[["__scopeId","data-v-89d9881f"]]);export{Ce as default};
|