appkit-assistant 0.17.3__py3-none-any.whl → 1.0.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.
- appkit_assistant/backend/{models.py → database/models.py} +32 -132
- appkit_assistant/backend/{repositories.py → database/repositories.py} +93 -1
- appkit_assistant/backend/model_manager.py +5 -5
- appkit_assistant/backend/models/__init__.py +28 -0
- appkit_assistant/backend/models/anthropic.py +31 -0
- appkit_assistant/backend/models/google.py +27 -0
- appkit_assistant/backend/models/openai.py +50 -0
- appkit_assistant/backend/models/perplexity.py +56 -0
- appkit_assistant/backend/processors/__init__.py +29 -0
- appkit_assistant/backend/processors/claude_responses_processor.py +205 -387
- appkit_assistant/backend/processors/gemini_responses_processor.py +231 -299
- appkit_assistant/backend/processors/lorem_ipsum_processor.py +6 -4
- appkit_assistant/backend/processors/mcp_mixin.py +297 -0
- appkit_assistant/backend/processors/openai_base.py +11 -125
- appkit_assistant/backend/processors/openai_chat_completion_processor.py +5 -3
- appkit_assistant/backend/processors/openai_responses_processor.py +480 -402
- appkit_assistant/backend/processors/perplexity_processor.py +156 -79
- appkit_assistant/backend/{processor.py → processors/processor_base.py} +7 -2
- appkit_assistant/backend/processors/streaming_base.py +188 -0
- appkit_assistant/backend/schemas.py +138 -0
- appkit_assistant/backend/services/auth_error_detector.py +99 -0
- appkit_assistant/backend/services/chunk_factory.py +273 -0
- appkit_assistant/backend/services/citation_handler.py +292 -0
- appkit_assistant/backend/services/file_cleanup_service.py +316 -0
- appkit_assistant/backend/services/file_upload_service.py +903 -0
- appkit_assistant/backend/services/file_validation.py +138 -0
- appkit_assistant/backend/{mcp_auth_service.py → services/mcp_auth_service.py} +4 -2
- appkit_assistant/backend/services/mcp_token_service.py +61 -0
- appkit_assistant/backend/services/message_converter.py +289 -0
- appkit_assistant/backend/services/openai_client_service.py +120 -0
- appkit_assistant/backend/{response_accumulator.py → services/response_accumulator.py} +163 -1
- appkit_assistant/backend/services/system_prompt_builder.py +89 -0
- appkit_assistant/backend/services/thread_service.py +5 -3
- appkit_assistant/backend/system_prompt_cache.py +3 -3
- appkit_assistant/components/__init__.py +8 -4
- appkit_assistant/components/composer.py +59 -24
- appkit_assistant/components/file_manager.py +623 -0
- appkit_assistant/components/mcp_server_dialogs.py +12 -20
- appkit_assistant/components/mcp_server_table.py +12 -2
- appkit_assistant/components/message.py +119 -2
- appkit_assistant/components/thread.py +1 -1
- appkit_assistant/components/threadlist.py +4 -2
- appkit_assistant/components/tools_modal.py +37 -20
- appkit_assistant/configuration.py +12 -0
- appkit_assistant/state/file_manager_state.py +697 -0
- appkit_assistant/state/mcp_oauth_state.py +3 -3
- appkit_assistant/state/mcp_server_state.py +47 -2
- appkit_assistant/state/system_prompt_state.py +1 -1
- appkit_assistant/state/thread_list_state.py +99 -5
- appkit_assistant/state/thread_state.py +88 -9
- {appkit_assistant-0.17.3.dist-info → appkit_assistant-1.0.0.dist-info}/METADATA +8 -6
- appkit_assistant-1.0.0.dist-info/RECORD +58 -0
- appkit_assistant/backend/processors/claude_base.py +0 -178
- appkit_assistant/backend/processors/gemini_base.py +0 -84
- appkit_assistant-0.17.3.dist-info/RECORD +0 -39
- /appkit_assistant/backend/{file_manager.py → services/file_manager.py} +0 -0
- {appkit_assistant-0.17.3.dist-info → appkit_assistant-1.0.0.dist-info}/WHEEL +0 -0
|
@@ -9,8 +9,8 @@ from reflex.vars import var_operation, var_operation_return
|
|
|
9
9
|
from reflex.vars.base import RETURN, CustomVarOperationReturn
|
|
10
10
|
|
|
11
11
|
import appkit_mantine as mn
|
|
12
|
-
from appkit_assistant.backend.
|
|
13
|
-
from appkit_assistant.backend.
|
|
12
|
+
from appkit_assistant.backend.database.models import MCPAuthType, MCPServer
|
|
13
|
+
from appkit_assistant.backend.services.mcp_auth_service import MCPAuthService
|
|
14
14
|
from appkit_assistant.state.mcp_server_state import MCPServerState
|
|
15
15
|
from appkit_ui.components.dialogs import (
|
|
16
16
|
delete_dialog,
|
|
@@ -280,7 +280,7 @@ def json(obj: rx.Var, indent: int = 4) -> CustomVarOperationReturn[RETURN]:
|
|
|
280
280
|
def _auth_type_selector() -> rx.Component:
|
|
281
281
|
"""Radio for selecting authentication type."""
|
|
282
282
|
return rx.box(
|
|
283
|
-
rx.
|
|
283
|
+
rx.heading("Authentifizierung", size="3", margin_bottom="9px"),
|
|
284
284
|
rx.radio_group.root(
|
|
285
285
|
rx.flex(
|
|
286
286
|
rx.flex(
|
|
@@ -302,7 +302,7 @@ def _auth_type_selector() -> rx.Component:
|
|
|
302
302
|
name="auth_type",
|
|
303
303
|
),
|
|
304
304
|
width="100%",
|
|
305
|
-
|
|
305
|
+
margin_bottom="12px",
|
|
306
306
|
)
|
|
307
307
|
|
|
308
308
|
|
|
@@ -338,18 +338,6 @@ def _oauth_auth_fields(server: MCPServer | None = None) -> rx.Component:
|
|
|
338
338
|
return rx.cond(
|
|
339
339
|
ValidationState.is_oauth_mode,
|
|
340
340
|
rx.flex(
|
|
341
|
-
rx.box(
|
|
342
|
-
rx.callout(
|
|
343
|
-
"OAuth 2.0 ermöglicht eine sichere Anmeldung über den "
|
|
344
|
-
"Identitätsanbieter des MCP-Servers. Die OAuth-Endpunkte "
|
|
345
|
-
"können automatisch ermittelt oder manuell konfiguriert werden.",
|
|
346
|
-
icon="info",
|
|
347
|
-
size="1",
|
|
348
|
-
color="blue",
|
|
349
|
-
),
|
|
350
|
-
width="100%",
|
|
351
|
-
mb="3",
|
|
352
|
-
),
|
|
353
341
|
# Primary Fields (Client ID / Secret)
|
|
354
342
|
form_field(
|
|
355
343
|
name="oauth_client_id",
|
|
@@ -364,7 +352,7 @@ def _oauth_auth_fields(server: MCPServer | None = None) -> rx.Component:
|
|
|
364
352
|
on_change=ValidationState.set_oauth_client_id,
|
|
365
353
|
on_blur=ValidationState.validate_oauth_client_id,
|
|
366
354
|
validation_error=ValidationState.oauth_client_id_error,
|
|
367
|
-
autocomplete="
|
|
355
|
+
autocomplete="one-time-code",
|
|
368
356
|
),
|
|
369
357
|
form_field(
|
|
370
358
|
name="oauth_client_secret",
|
|
@@ -379,9 +367,9 @@ def _oauth_auth_fields(server: MCPServer | None = None) -> rx.Component:
|
|
|
379
367
|
on_change=ValidationState.set_oauth_client_secret,
|
|
380
368
|
on_blur=ValidationState.validate_oauth_client_secret,
|
|
381
369
|
validation_error=ValidationState.oauth_client_secret_error,
|
|
382
|
-
autocomplete="
|
|
370
|
+
autocomplete="new-password",
|
|
383
371
|
),
|
|
384
|
-
rx.
|
|
372
|
+
rx.heading("OAuth Endpunkte & Scopes", size="3", margin_top="12px"),
|
|
385
373
|
# Additional Discovery Fields (Editable)
|
|
386
374
|
form_field(
|
|
387
375
|
name="oauth_issuer",
|
|
@@ -579,7 +567,11 @@ def add_mcp_server_button() -> rx.Component:
|
|
|
579
567
|
),
|
|
580
568
|
rx.flex(
|
|
581
569
|
rx.form.root(
|
|
582
|
-
|
|
570
|
+
mn.scroll_area(
|
|
571
|
+
mcp_server_form_fields(),
|
|
572
|
+
height="60vh",
|
|
573
|
+
width="100%",
|
|
574
|
+
),
|
|
583
575
|
dialog_buttons(
|
|
584
576
|
"MCP Server anlegen",
|
|
585
577
|
has_errors=ValidationState.has_errors,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import reflex as rx
|
|
4
4
|
from reflex.components.radix.themes.components.table import TableRow
|
|
5
5
|
|
|
6
|
-
from appkit_assistant.backend.models import MCPServer
|
|
6
|
+
from appkit_assistant.backend.database.models import MCPServer
|
|
7
7
|
from appkit_assistant.components.mcp_server_dialogs import (
|
|
8
8
|
add_mcp_server_button,
|
|
9
9
|
delete_mcp_server_dialog,
|
|
@@ -36,6 +36,15 @@ def mcp_server_table_row(server: MCPServer) -> TableRow:
|
|
|
36
36
|
"width": "100%",
|
|
37
37
|
},
|
|
38
38
|
),
|
|
39
|
+
rx.table.cell(
|
|
40
|
+
rx.switch(
|
|
41
|
+
checked=server.active,
|
|
42
|
+
on_change=lambda checked: MCPServerState.toggle_server_active(
|
|
43
|
+
server.id, checked
|
|
44
|
+
),
|
|
45
|
+
),
|
|
46
|
+
white_space="nowrap",
|
|
47
|
+
),
|
|
39
48
|
rx.table.cell(
|
|
40
49
|
rx.hstack(
|
|
41
50
|
update_mcp_server_dialog(server),
|
|
@@ -62,8 +71,9 @@ def mcp_servers_table() -> rx.Fragment:
|
|
|
62
71
|
rx.table.row(
|
|
63
72
|
rx.table.column_header_cell("Name", width="20%"),
|
|
64
73
|
rx.table.column_header_cell(
|
|
65
|
-
"Beschreibung", width="calc(80% -
|
|
74
|
+
"Beschreibung", width="calc(80% - 230px)"
|
|
66
75
|
),
|
|
76
|
+
rx.table.column_header_cell("Aktiv", width="90px"),
|
|
67
77
|
rx.table.column_header_cell("", width="140px"),
|
|
68
78
|
),
|
|
69
79
|
),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import reflex as rx
|
|
2
2
|
|
|
3
3
|
import appkit_mantine as mn
|
|
4
|
-
from appkit_assistant.backend.
|
|
4
|
+
from appkit_assistant.backend.schemas import (
|
|
5
5
|
Message,
|
|
6
6
|
MessageType,
|
|
7
7
|
Thinking,
|
|
@@ -150,6 +150,60 @@ class MessageActionsBar:
|
|
|
150
150
|
)
|
|
151
151
|
|
|
152
152
|
|
|
153
|
+
def _render_annotation(ann: str) -> rx.Component:
|
|
154
|
+
return rx.cond(
|
|
155
|
+
ann.contains("http"),
|
|
156
|
+
rx.badge(
|
|
157
|
+
rx.link(
|
|
158
|
+
rx.hstack(
|
|
159
|
+
rx.icon("globe", size=12, flex_shrink=0),
|
|
160
|
+
rx.text(
|
|
161
|
+
ann,
|
|
162
|
+
style={
|
|
163
|
+
"overflow": "hidden",
|
|
164
|
+
"white_space": "nowrap",
|
|
165
|
+
"text_overflow": "ellipsis",
|
|
166
|
+
},
|
|
167
|
+
),
|
|
168
|
+
align="center",
|
|
169
|
+
spacing="1",
|
|
170
|
+
width="100%",
|
|
171
|
+
),
|
|
172
|
+
href=ann,
|
|
173
|
+
is_external=True,
|
|
174
|
+
size="1",
|
|
175
|
+
width="100%",
|
|
176
|
+
text_decoration="none",
|
|
177
|
+
style={"overflow": "hidden"},
|
|
178
|
+
),
|
|
179
|
+
size="1",
|
|
180
|
+
variant="soft",
|
|
181
|
+
color_scheme="gray",
|
|
182
|
+
max_width="100%",
|
|
183
|
+
),
|
|
184
|
+
rx.badge(
|
|
185
|
+
rx.hstack(
|
|
186
|
+
rx.icon("file-text", size=12, flex_shrink=0),
|
|
187
|
+
rx.text(
|
|
188
|
+
ann,
|
|
189
|
+
style={
|
|
190
|
+
"overflow": "hidden",
|
|
191
|
+
"white_space": "nowrap",
|
|
192
|
+
"text_overflow": "ellipsis",
|
|
193
|
+
},
|
|
194
|
+
),
|
|
195
|
+
align="center",
|
|
196
|
+
spacing="1",
|
|
197
|
+
width="100%",
|
|
198
|
+
),
|
|
199
|
+
size="1",
|
|
200
|
+
variant="soft",
|
|
201
|
+
color_scheme="gray",
|
|
202
|
+
max_width="100%",
|
|
203
|
+
),
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
|
|
153
207
|
class MessageComponent:
|
|
154
208
|
@staticmethod
|
|
155
209
|
def _file_badge(filename: str) -> rx.Component:
|
|
@@ -348,6 +402,37 @@ class MessageComponent:
|
|
|
348
402
|
max_width="90%",
|
|
349
403
|
),
|
|
350
404
|
),
|
|
405
|
+
# Annotations/Sources
|
|
406
|
+
rx.cond(
|
|
407
|
+
message.annotations.length() > 0,
|
|
408
|
+
rx.vstack(
|
|
409
|
+
rx.hstack(
|
|
410
|
+
rx.icon("file-text", size=13, color=rx.color("gray", 9)),
|
|
411
|
+
rx.text(
|
|
412
|
+
"Quellen:",
|
|
413
|
+
size="1",
|
|
414
|
+
color=rx.color("gray", 9),
|
|
415
|
+
),
|
|
416
|
+
spacing="1",
|
|
417
|
+
),
|
|
418
|
+
rx.hstack(
|
|
419
|
+
rx.foreach(
|
|
420
|
+
message.annotations,
|
|
421
|
+
_render_annotation,
|
|
422
|
+
),
|
|
423
|
+
spacing="2",
|
|
424
|
+
align="start",
|
|
425
|
+
flex_wrap="wrap",
|
|
426
|
+
max_width="95%",
|
|
427
|
+
),
|
|
428
|
+
padding="6px",
|
|
429
|
+
margin_top="6px",
|
|
430
|
+
margin_bottom="6px",
|
|
431
|
+
width="90%",
|
|
432
|
+
align="start",
|
|
433
|
+
),
|
|
434
|
+
rx.fragment(),
|
|
435
|
+
),
|
|
351
436
|
# Actions bar
|
|
352
437
|
rx.cond(
|
|
353
438
|
message.done,
|
|
@@ -482,7 +567,11 @@ class ToolCallComponent:
|
|
|
482
567
|
return rx.cond(
|
|
483
568
|
tool_item.type == ThinkingType.REASONING,
|
|
484
569
|
ToolCallComponent._render_reasoning(tool_item),
|
|
485
|
-
|
|
570
|
+
rx.cond(
|
|
571
|
+
tool_item.type == ThinkingType.PROCESSING,
|
|
572
|
+
ToolCallComponent._render_processing(tool_item),
|
|
573
|
+
ToolCallComponent._render_tool_call(tool_item),
|
|
574
|
+
),
|
|
486
575
|
)
|
|
487
576
|
|
|
488
577
|
@staticmethod
|
|
@@ -494,6 +583,34 @@ class ToolCallComponent:
|
|
|
494
583
|
margin_bottom="9px",
|
|
495
584
|
)
|
|
496
585
|
|
|
586
|
+
@staticmethod
|
|
587
|
+
def _render_processing(item: Thinking) -> rx.Component:
|
|
588
|
+
"""Render file processing progress."""
|
|
589
|
+
return rx.hstack(
|
|
590
|
+
rx.cond(
|
|
591
|
+
item.status == ThinkingStatus.COMPLETED,
|
|
592
|
+
rx.icon("circle-check", size=14, color=rx.color("green", 9)),
|
|
593
|
+
rx.cond(
|
|
594
|
+
item.status == ThinkingStatus.ERROR,
|
|
595
|
+
rx.icon("circle-x", size=14, color=rx.color("red", 9)),
|
|
596
|
+
rx.icon("file-up", size=14, color=rx.color("blue", 9)),
|
|
597
|
+
),
|
|
598
|
+
),
|
|
599
|
+
rx.text(
|
|
600
|
+
item.text,
|
|
601
|
+
size="1",
|
|
602
|
+
color=rx.cond(
|
|
603
|
+
item.status == ThinkingStatus.ERROR,
|
|
604
|
+
rx.color("red", 9),
|
|
605
|
+
rx.color("gray", 10),
|
|
606
|
+
),
|
|
607
|
+
),
|
|
608
|
+
spacing="2",
|
|
609
|
+
padding="3px 6px",
|
|
610
|
+
margin_bottom="3px",
|
|
611
|
+
width="100%",
|
|
612
|
+
)
|
|
613
|
+
|
|
497
614
|
@staticmethod
|
|
498
615
|
def _render_tool_call(item: Thinking) -> rx.Component:
|
|
499
616
|
return rx.vstack(
|
|
@@ -4,7 +4,7 @@ from collections.abc import Callable
|
|
|
4
4
|
import reflex as rx
|
|
5
5
|
|
|
6
6
|
import appkit_mantine as mn
|
|
7
|
-
from appkit_assistant.backend.
|
|
7
|
+
from appkit_assistant.backend.schemas import Message, MessageType
|
|
8
8
|
from appkit_assistant.components import composer
|
|
9
9
|
from appkit_assistant.components.message import AuthCardComponent, MessageComponent
|
|
10
10
|
from appkit_assistant.components.threadlist import ThreadList
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import reflex as rx
|
|
2
2
|
|
|
3
|
-
from appkit_assistant.backend.
|
|
3
|
+
from appkit_assistant.backend.schemas import ThreadModel
|
|
4
4
|
from appkit_assistant.state.thread_list_state import ThreadListState
|
|
5
5
|
from appkit_assistant.state.thread_state import ThreadState
|
|
6
6
|
|
|
@@ -63,7 +63,9 @@ class ThreadList:
|
|
|
63
63
|
margin_left="0px",
|
|
64
64
|
margin_right="0px",
|
|
65
65
|
color_scheme="gray",
|
|
66
|
-
on_click=ThreadListState.delete_thread(
|
|
66
|
+
on_click=ThreadListState.delete_thread(
|
|
67
|
+
thread.thread_id
|
|
68
|
+
).stop_propagation,
|
|
67
69
|
),
|
|
68
70
|
content="Chat löschen",
|
|
69
71
|
flex_shrink=0,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import reflex as rx
|
|
4
4
|
|
|
5
|
-
from appkit_assistant.backend.models import MCPServer
|
|
5
|
+
from appkit_assistant.backend.database.models import MCPServer
|
|
6
6
|
from appkit_assistant.state.thread_state import ThreadState
|
|
7
7
|
|
|
8
8
|
|
|
@@ -29,19 +29,22 @@ def render_mcp_server_item(server: MCPServer) -> rx.Component:
|
|
|
29
29
|
def tools_popover() -> rx.Component:
|
|
30
30
|
"""Render the tools modal popup."""
|
|
31
31
|
return rx.popover.root(
|
|
32
|
-
rx.
|
|
33
|
-
rx.
|
|
34
|
-
rx.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
rx.tooltip(
|
|
33
|
+
rx.popover.trigger(
|
|
34
|
+
rx.button(
|
|
35
|
+
rx.icon("pencil-ruler", size=17),
|
|
36
|
+
rx.text(
|
|
37
|
+
ThreadState.selected_mcp_servers.length().to_string()
|
|
38
|
+
+ " von "
|
|
39
|
+
+ ThreadState.available_mcp_servers.length().to_string(),
|
|
40
|
+
size="1",
|
|
41
|
+
),
|
|
42
|
+
cursor="pointer",
|
|
43
|
+
variant="ghost",
|
|
44
|
+
padding="8px",
|
|
40
45
|
),
|
|
41
|
-
variant="ghost",
|
|
42
|
-
size="2",
|
|
43
|
-
border_radius="4px",
|
|
44
46
|
),
|
|
47
|
+
content="Werkzeuge verwalten",
|
|
45
48
|
),
|
|
46
49
|
rx.popover.content(
|
|
47
50
|
rx.vstack(
|
|
@@ -49,8 +52,7 @@ def tools_popover() -> rx.Component:
|
|
|
49
52
|
rx.cond(
|
|
50
53
|
ThreadState.available_mcp_servers.length() > 0,
|
|
51
54
|
rx.text(
|
|
52
|
-
"Wähle
|
|
53
|
-
"verfügbar sein sollen.",
|
|
55
|
+
"Wähle deine Werkzeuge für diese Unterhaltung aus.",
|
|
54
56
|
size="2",
|
|
55
57
|
color="gray",
|
|
56
58
|
margin_bottom="1.5em",
|
|
@@ -73,16 +75,31 @@ def tools_popover() -> rx.Component:
|
|
|
73
75
|
width="100%",
|
|
74
76
|
),
|
|
75
77
|
width="100%",
|
|
76
|
-
max_height="
|
|
78
|
+
max_height="calc(66vh - 180px)",
|
|
77
79
|
scrollbars="vertical",
|
|
78
80
|
type="auto",
|
|
79
81
|
),
|
|
80
|
-
rx.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
rx.hstack(
|
|
83
|
+
rx.button(
|
|
84
|
+
"Anwenden",
|
|
85
|
+
on_click=ThreadState.apply_mcp_server_selection,
|
|
86
|
+
variant="solid",
|
|
87
|
+
color_scheme="blue",
|
|
88
|
+
),
|
|
89
|
+
rx.tooltip(
|
|
90
|
+
rx.button(
|
|
91
|
+
rx.icon("paintbrush", size=17),
|
|
92
|
+
cursor="pointer",
|
|
93
|
+
variant="ghost",
|
|
94
|
+
padding="8px",
|
|
95
|
+
margin_left="6px",
|
|
96
|
+
on_click=ThreadState.deselect_all_mcp_servers,
|
|
97
|
+
),
|
|
98
|
+
content="Alle abwählen",
|
|
99
|
+
),
|
|
100
|
+
spacing="2",
|
|
85
101
|
margin_top="1.5em",
|
|
102
|
+
align="center",
|
|
86
103
|
),
|
|
87
104
|
spacing="1",
|
|
88
105
|
),
|
|
@@ -3,11 +3,23 @@ from pydantic import SecretStr
|
|
|
3
3
|
from appkit_commons.configuration import BaseConfig
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
class FileUploadConfig(BaseConfig):
|
|
7
|
+
"""Configuration for file upload and vector store management."""
|
|
8
|
+
|
|
9
|
+
vector_store_expiration_days: int = 2
|
|
10
|
+
max_file_size_mb: int = 50
|
|
11
|
+
max_files_per_thread: int = 10
|
|
12
|
+
cleanup_interval_minutes: int = 60
|
|
13
|
+
files_expiration_days: int = 30
|
|
14
|
+
|
|
15
|
+
|
|
6
16
|
class AssistantConfig(BaseConfig):
|
|
7
17
|
perplexity_api_key: SecretStr | None = None
|
|
8
18
|
openai_base_url: str | None = None
|
|
9
19
|
openai_api_key: SecretStr | None = None
|
|
20
|
+
openai_is_azure: bool = False
|
|
10
21
|
claude_base_url: str | None = None
|
|
11
22
|
claude_api_key: SecretStr | None = None
|
|
12
23
|
google_api_key: SecretStr | None = None
|
|
13
24
|
azure_ai_projects_endpoint: str | None = None
|
|
25
|
+
file_upload: FileUploadConfig = FileUploadConfig()
|